From 47429dd1bf5eaed408ebb52d5fe9bd2fdf0215e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 7 Nov 2017 22:55:28 +0000 Subject: [PATCH 001/175] Proof of concept attempt to implement KAuth. --- CMakeLists.txt | 1 + src/CMakeLists.txt | 1 + src/backend/corebackendmanager.cpp | 3 + src/backend/corebackendmanager.h | 9 ++ src/fs/fat16.cpp | 4 +- src/fs/fat32.cpp | 4 +- src/fs/filesystem.cpp | 10 +- src/fs/jfs.cpp | 2 +- src/fs/luks.cpp | 10 +- src/fs/ntfs.cpp | 3 +- src/fs/ocfs2.cpp | 4 +- src/fs/reiserfs.cpp | 4 +- src/fs/udf.cpp | 5 +- src/plugins/sfdisk/sfdiskdevice.cpp | 6 +- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 8 +- src/util/CMakeLists.txt | 7 ++ src/util/externalcommand.cpp | 106 +++++++++++++----- src/util/externalcommand.h | 20 +++- src/util/externalcommandhelper.cpp | 59 ++++++++++ src/util/externalcommandhelper.h | 42 +++++++ .../org.kde.kpmcore.externalcommand.actions | 5 + test/CMakeLists.txt | 7 ++ test/testexternalcommand.cpp | 66 +++++++++++ 23 files changed, 323 insertions(+), 63 deletions(-) create mode 100644 src/util/externalcommandhelper.cpp create mode 100644 src/util/externalcommandhelper.h create mode 100644 src/util/org.kde.kpmcore.externalcommand.actions create mode 100644 test/testexternalcommand.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f863a7..ec5046e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS # Load the frameworks we need find_package(KF5 REQUIRED + Auth I18n CoreAddons WidgetsAddons diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6708a64..1fea707 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ target_link_libraries( kpmcore ${BLKID_LIBRARIES} ${LIBATASMART_LIBRARIES} Qt5::DBus + KF5::Auth KF5::I18n KF5::CoreAddons KF5::WidgetsAddons diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 7ddef4c..5014252 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,8 @@ CoreBackendManager::CoreBackendManager() : m_Backend(nullptr) { + m_KAuthThread = new QThread(); + kauthThread()->start(); } CoreBackendManager* CoreBackendManager::self() diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index 9946292..7460136 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -23,6 +23,7 @@ #include +class QThread; class QString; class QStringList; class KPluginMetaData; @@ -77,8 +78,16 @@ public: return m_Backend; } + /** + * @return a pointer to the thread where ExternalCommand will start KAuth job + */ + QThread* kauthThread() { + return m_KAuthThread; + } + private: CoreBackend* m_Backend; + QThread* m_KAuthThread; }; #endif diff --git a/src/fs/fat16.cpp b/src/fs/fat16.cpp index 5aa6eb5..da01349 100644 --- a/src/fs/fat16.cpp +++ b/src/fs/fat16.cpp @@ -177,10 +177,10 @@ bool fat16::updateUUID(Report& report, const QString& deviceNode) const ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") }); - if (!cmd.start()) + if (!cmd.write(QByteArray(uuid, sizeof(uuid)))) return false; - if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid)) + if (!cmd.start()) return false; return cmd.waitFor(-1); diff --git a/src/fs/fat32.cpp b/src/fs/fat32.cpp index 2dd891c..05e30c8 100644 --- a/src/fs/fat32.cpp +++ b/src/fs/fat32.cpp @@ -59,10 +59,10 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const // 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") }); - if (!cmd.start()) + if (!cmd.write(QByteArray(uuid, sizeof(uuid)))) return false; - if (cmd.write(uuid, sizeof(uuid)) != sizeof(uuid)) + if (!cmd.start()) return false; return cmd.waitFor(-1); diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index fa2413c..a3c6449 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -34,6 +34,7 @@ #include #include +#include #include const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode = @@ -548,13 +549,14 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode) return false; } +// FIXME: args and expectedCode is now unused. bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode) { - ExternalCommand cmd(cmdName, args); - if (!cmd.run()) - return false; + QString cmd = QStandardPaths::findExecutable(cmdName); + if (cmd.isEmpty()) + cmd = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); - return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode; + return !cmd.isEmpty(); } bool FileSystem::supportToolFound() const diff --git a/src/fs/jfs.cpp b/src/fs/jfs.cpp index 8d3362f..90ab7ba 100644 --- a/src/fs/jfs.cpp +++ b/src/fs/jfs.cpp @@ -96,7 +96,7 @@ qint64 jfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode); - if (cmd.start() && cmd.write("dm") == 2 && cmd.waitFor()) { + if (cmd.write(QByteArrayLiteral("dm")) && cmd.start() && cmd.waitFor()) { qint64 blockSize = -1; QRegularExpression re(QStringLiteral("Block Size: (\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index 91402c2..57c309e 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -127,8 +127,8 @@ bool luks::create(Report& report, const QString& deviceNode) QStringLiteral("--force-password"), QStringLiteral("luksFormat"), deviceNode }); - if (!( createCmd.start(-1) && - createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && + if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && + createCmd.start(-1) && createCmd.waitFor() && createCmd.exitCode() == 0)) { return false; @@ -139,7 +139,7 @@ bool luks::create(Report& report, const QString& deviceNode) deviceNode, suggestedMapperName(deviceNode) }); - if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor())) + if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) return false; scan(deviceNode); @@ -261,8 +261,8 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) deviceNode, suggestedMapperName(deviceNode) }); - if (!( openCmd.start(-1) && - openCmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 && + if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') && + openCmd.start(-1) && openCmd.waitFor() && openCmd.exitCode() == 0) ) return false; diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index 9fedf0a..f925127 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -125,8 +125,7 @@ qint64 ntfs::readUsedCapacity(const QString& deviceNode) const bool ntfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { - ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }); - writeCmd.setProcessChannelMode(QProcess::SeparateChannels); + ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }, QProcess::SeparateChannels); if (!writeCmd.run(-1)) return false; diff --git a/src/fs/ocfs2.cpp b/src/fs/ocfs2.cpp index dfd7366..03720c4 100644 --- a/src/fs/ocfs2.cpp +++ b/src/fs/ocfs2.cpp @@ -113,9 +113,9 @@ bool ocfs2::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode }); - if (cmd.start()) + if (cmd.write("y\n")) { - cmd.write("y\n"); + cmd.start(); cmd.waitFor(-1); return cmd.exitCode() == 0; diff --git a/src/fs/reiserfs.cpp b/src/fs/reiserfs.cpp index bb94d81..2f8a7ef 100644 --- a/src/fs/reiserfs.cpp +++ b/src/fs/reiserfs.cpp @@ -154,12 +154,12 @@ bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length) ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"), { deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) }); - bool rval = cmd.start(-1); + bool rval = cmd.write(QByteArrayLiteral("y\n")); if (!rval) return false; - if (cmd.write("y\n", 2) != 2) + if (!cmd.start(-1)) return false; return cmd.waitFor(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 256); diff --git a/src/fs/udf.cpp b/src/fs/udf.cpp index a33ae44..ca66d49 100644 --- a/src/fs/udf.cpp +++ b/src/fs/udf.cpp @@ -47,8 +47,9 @@ void udf::init() if (m_Create == cmdSupportFileSystem) { // Detect old mkudffs prior to version 1.1 by lack of --label option - ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") }); - oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label")); +// ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") }); +// oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label")); + oldMkudffsVersion = false; } } diff --git a/src/plugins/sfdisk/sfdiskdevice.cpp b/src/plugins/sfdisk/sfdiskdevice.cpp index f373df7..8ed89ab 100644 --- a/src/plugins/sfdisk/sfdiskdevice.cpp +++ b/src/plugins/sfdisk/sfdiskdevice.cpp @@ -74,8 +74,8 @@ bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& pt tableType = ptable.typeName().toLocal8Bit(); ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { m_device->deviceNode() } ); - if ( createCommand.start(-1) && createCommand.write(QByteArrayLiteral("label: ") + tableType + - QByteArrayLiteral("\nwrite\n")) && createCommand.waitFor() ) { + if ( createCommand.write(QByteArrayLiteral("label: ") + tableType + + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { return createCommand.output().contains(QStringLiteral("Script header accepted.")); } @@ -112,7 +112,7 @@ bool SfdiskDevice::writeData(QByteArray& buffer, qint64 offset) QStringLiteral("bs=1M"), QStringLiteral("oflag=seek_bytes"), QStringLiteral("conv=fsync") }, QProcess::SeparateChannels); - if ( ddCommand.start(-1) && ddCommand.write(buffer) == buffer.size() && ddCommand.waitFor() && ddCommand.exitCode() == 0 ) { + if ( ddCommand.write(buffer) && ddCommand.start(-1) && ddCommand.waitFor() && ddCommand.exitCode() == 0 ) { return true; } diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index fd5208b..9e06bff 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -74,9 +74,9 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p // NOTE: at least on GPT partition types "are" partition flags ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), QStringLiteral("--append"), partition.devicePath() } ); - if ( createCommand.start(-1) && createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) + + if ( createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) + type + - QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.waitFor() ) { + QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { QRegularExpression re(QStringLiteral("Created a new partition (\\d)")); QRegularExpressionMatch rem = re.match(createCommand.output()); if (rem.hasMatch()) @@ -101,10 +101,10 @@ bool SfdiskPartitionTable::deletePartition(Report& report, const Partition& part bool SfdiskPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sectorStart, qint64 sectorEnd) { ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), partition.devicePath(), QStringLiteral("-N"), QString::number(partition.number()) } ); - if ( sfdiskCommand.start(-1) && sfdiskCommand.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) + + if ( sfdiskCommand.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) + QByteArrayLiteral(" size=") + QByteArray::number(sectorEnd - sectorStart + 1) + QByteArrayLiteral("\nY\n")) - && sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) { + && sfdiskCommand.start(-1) && sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) { return true; } diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index c8b2ea3..439348e 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -16,3 +16,10 @@ set(UTIL_LIB_HDRS util/htmlreport.h util/report.h ) + +add_executable(kpmcore_externalcommand util/externalcommandhelper.cpp) +target_link_libraries(kpmcore_externalcommand KF5::Auth) +install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) + +kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root) +kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 2bbc8fc..6ad4971 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -16,14 +16,20 @@ * along with this program. If not, see .* *************************************************************************/ +#include "backend/corebackendmanager.h" #include "util/externalcommand.h" - #include "util/report.h" +#include +#include #include +#include #include #include +#include +#include +#include #include /** Creates a new ExternalCommand instance without Report. @@ -31,7 +37,6 @@ @param args the arguments to pass to the command */ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : - QProcess(), m_Report(nullptr), m_Command(cmd), m_Args(args), @@ -47,7 +52,6 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co @param args the arguments to pass to the command */ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : - QProcess(), m_Report(report.newChild()), m_Command(cmd), m_Args(args), @@ -59,11 +63,11 @@ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStri void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMode) { - setEnvironment(QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("PATH=") + QString::fromLocal8Bit(getenv("PATH")) << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); - setProcessChannelMode(processChannelMode); + arguments.insert(QStringLiteral("environment"), QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); + arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); - connect(this, qOverload(&QProcess::finished), this, &ExternalCommand::onFinished); - connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); +// connect(this, qOverload(&QProcess::finished), this, &ExternalCommand::onFinished); +// connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); } /** Starts the external command. @@ -72,19 +76,61 @@ void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMod */ bool ExternalCommand::start(int timeout) { - QProcess::start(command(), args()); + this->moveToThread(CoreBackendManager::self()->kauthThread()); + QTimer::singleShot(0, this, &ExternalCommand::execute); + QEventLoop loop; + connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); + loop.exec(); + return true; +} +/** Executes the external command in kauthThread() thread. +*/ +void ExternalCommand::execute() +{ if (report()) { report()->setCommand(xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" ")))); } - if (!waitForStarted(timeout)) - { - if (report()) - report()->line() << xi18nc("@info:status", "(Command timeout while starting)"); - return false; + QString cmd = QStandardPaths::findExecutable(command()); + if (cmd.isEmpty()) + cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); + + KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.start")); + action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); + arguments.insert(QStringLiteral("command"), cmd); + arguments.insert(QStringLiteral("input"), m_Input); + arguments.insert(QStringLiteral("arguments"), args()); + action.setArguments(arguments); + + KAuth::ExecuteJob *job = action.execute(); + if (!job->exec()) { + qWarning() << "KAuth returned an error code: " << job->errorString(); +// return false; + emit finished(); + return; } + m_Output = job->data()[QStringLiteral("output")].toByteArray(); + setExitCode(job->data()[QStringLiteral("exitCode")].toInt()); + +// QProcess::start(command(), args()); + + // FIXME +// if (!waitForStarted(timeout)) +// { +// if (report()) +// report()->line() << xi18nc("@info:status", "(Command timeout while starting)"); +// return false; +// } + +// return true; + emit finished(); +} + +bool ExternalCommand::write(const QByteArray& input) +{ + m_Input = input; return true; } @@ -94,15 +140,15 @@ bool ExternalCommand::start(int timeout) */ bool ExternalCommand::waitFor(int timeout) { - closeWriteChannel(); - +// closeWriteChannel(); +/* if (!waitForFinished(timeout)) { if (report()) report()->line() << xi18nc("@info:status", "(Command timeout while running)"); return false; - } + }*/ - onReadOutput(); +// onReadOutput(); return true; } @@ -112,23 +158,23 @@ bool ExternalCommand::waitFor(int timeout) */ bool ExternalCommand::run(int timeout) { - return start(timeout) && waitFor(timeout) && exitStatus() == 0; + return start(timeout) && waitFor(timeout)/* && exitStatus() == 0*/; } void ExternalCommand::onReadOutput() { - const QByteArray s = readAllStandardOutput(); - - if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems - if (report()) - report()->line() << xi18nc("@info:status", "(Command is printing too much output)"); - return; - } - - m_Output += s; - - if (report()) - *report() << QString::fromLocal8Bit(s); +// const QByteArray s = readAllStandardOutput(); +// +// if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems +// if (report()) +// report()->line() << xi18nc("@info:status", "(Command is printing too much output)"); +// return; +// } +// +// m_Output += s; +// +// if (report()) +// *report() << QString::fromLocal8Bit(s); } void ExternalCommand::onFinished(int exitCode, QProcess::ExitStatus exitStatus) diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 9b0b9cc..ee9cea4 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -21,10 +21,12 @@ #include "util/libpartitionmanagerexport.h" +#include +#include #include #include #include -#include +#include class Report; @@ -35,13 +37,14 @@ class Report; @author Volker Lanz @author Andrius Štikonas */ -class LIBKPMCORE_EXPORT ExternalCommand : public QProcess +class LIBKPMCORE_EXPORT ExternalCommand : public QObject { + Q_OBJECT Q_DISABLE_COPY(ExternalCommand) public: - explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = MergedChannels); - explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = MergedChannels); + explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); + explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); public: void setCommand(const QString& cmd) { m_Command = cmd; } /**< @param cmd the command to run */ @@ -50,6 +53,7 @@ public: void addArg(const QString& s) { m_Args << s; } /**< @param s the argument to add */ const QStringList& args() const { return m_Args; } /**< @return the arguments */ void setArgs(const QStringList& args) { m_Args = args; } /**< @param args the new arguments */ + bool write(const QByteArray& input); /**< @param input the input for the program */ bool start(int timeout = 30000); bool waitFor(int timeout = 30000); @@ -71,7 +75,12 @@ public: return m_Report; /**< @return pointer to the Report or nullptr */ } +Q_SIGNALS: + void finished(); + protected: + void execute(); + void setExitCode(int i) { m_ExitCode = i; } @@ -81,11 +90,14 @@ protected: void onReadOutput(); private: + QVariantMap arguments; + Report *m_Report; QString m_Command; QStringList m_Args; int m_ExitCode; QByteArray m_Output; + QByteArray m_Input; }; #endif diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp new file mode 100644 index 0000000..c60d84c --- /dev/null +++ b/src/util/externalcommandhelper.cpp @@ -0,0 +1,59 @@ +/************************************************************************* + * Copyright (C) 2017 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "externalcommandhelper.h" + +#include + +ActionReply ExternalCommandHelper::start(const QVariantMap& args) +{ + ActionReply reply; + QString command = args[QStringLiteral("command")].toString(); + QStringList arguments = args[QStringLiteral("arguments")].toStringList(); + QStringList environment = args[QStringLiteral("environment")].toStringList(); + QByteArray input = args[QStringLiteral("input")].toByteArray(); + +// connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); + + cmd.setEnvironment(environment); + cmd.start(command, arguments); + cmd.write(input); + cmd.waitForFinished(-1); + QByteArray output = cmd.readAllStandardOutput(); + reply.addData(QStringLiteral("output"), output); + reply.addData(QStringLiteral("exitCode"), cmd.exitCode()); + + return reply; +} + +void ExternalCommandHelper::onReadOutput() +{ +// const QByteArray s = cmd.readAllStandardOutput(); + +// if(output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems +// if (report()) +// report()->line() << xi18nc("@info:status", "(Command is printing too much output)"); +// return; +// } + +// output += s; + +// if (report()) +// *report() << QString::fromLocal8Bit(s); +} + +KAUTH_HELPER_MAIN("org.kde.kpmcore.externalcommand", ExternalCommandHelper) diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h new file mode 100644 index 0000000..371a3d9 --- /dev/null +++ b/src/util/externalcommandhelper.h @@ -0,0 +1,42 @@ +/************************************************************************* + * Copyright (C) 2017 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#ifndef KPMCORE_EXTERNALCOMMANDHELPER_H + +#define KPMCORE_EXTERNALCOMMANDHELPER_H + +#include + +#include + +using namespace KAuth; + +class ExternalCommandHelper : public QObject +{ + Q_OBJECT + +public Q_SLOTS: + ActionReply start(const QVariantMap& args); + +private: + void onReadOutput(); + + QProcess cmd; +// QByteArray output; +}; + +#endif diff --git a/src/util/org.kde.kpmcore.externalcommand.actions b/src/util/org.kde.kpmcore.externalcommand.actions new file mode 100644 index 0000000..0a00710 --- /dev/null +++ b/src/util/org.kde.kpmcore.externalcommand.actions @@ -0,0 +1,5 @@ +[org.kde.kpmcore.externalcommand.start] +Name=Run external command action +Description=Run external command as privileged user +Policy=auth_admin +Persistence=session diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 81c8b4c..e81581e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,3 +45,10 @@ add_test(NAME testlist COMMAND testlist ${BACKEND}) kpm_test(testdevicescanner testdevicescanner.cpp) add_test(NAME testdevicescanner COMMAND testdevicescanner ${BACKEND}) + +find_package (Threads) +### +# +# Execute external commands as root +kpm_test(testexternalcommand testexternalcommand.cpp) +add_test(NAME testexternalcommand COMMAND testexternalcommand ${BACKEND}) diff --git a/test/testexternalcommand.cpp b/test/testexternalcommand.cpp new file mode 100644 index 0000000..5dbabac --- /dev/null +++ b/test/testexternalcommand.cpp @@ -0,0 +1,66 @@ +/************************************************************************* + * Copyright 2017 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +// SPDX-License-Identifier: GPL-3.0+ + + +#include "helpers.h" +#include "backend/corebackendmanager.h" +#include "util/externalcommand.h" + +#include +#include +#include + +class runcmd : public QThread { +public: + +void run() +{ + ExternalCommand blkidCmd(QStringLiteral("blkid"), {}); + blkidCmd.run(); + qDebug().noquote() << blkidCmd.output(); +} + +}; + +class runcmd2 : public QThread { +public: + +void run() +{ + ExternalCommand lsblkCmd(QStringLiteral("lsblk"), { QStringLiteral("--nodeps"), QStringLiteral("--json") }); + lsblkCmd.run(); + qDebug().noquote() << lsblkCmd.output(); +} +}; + + +int main( int argc, char **argv ) +{ + QApplication app(argc, argv); + KPMCoreInitializer i(QStringLiteral("pmsfdiskbackendplugin")); + + runcmd a; + runcmd2 b; + a.start(); + a.wait(); + b.start(); + b.wait(); + + return 0; +} From d2f13ff4ccf76a3c3e58dffbbe76735599d719c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 8 Dec 2017 18:56:34 +0000 Subject: [PATCH 002/175] QFile->QTemporaryFile. --- src/core/fstab.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index 6b88562..756a147 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -23,9 +23,9 @@ #include #include -#include #include #include +#include #include static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode); @@ -180,11 +180,11 @@ static void writeEntry(QFile& output, const FstabEntry& entry) bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename) { bool rval = true; - const QString newFilename = QStringLiteral("%1.new").arg(filename); - QFile out(newFilename); + QTemporaryFile out; + out.setAutoRemove(false); - if (!out.open(QFile::ReadWrite | QFile::Truncate)) { - qWarning() << "could not open output file " << newFilename; + if (!out.open()) { + qWarning() << "could not open output file " << out.fileName(); rval = false; } else { for (const auto &e : fstabEntries) @@ -200,8 +200,8 @@ bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename rval = false; } - if (rval && !QFile::rename(newFilename, filename)) { - qWarning() << "could not rename " << newFilename << " to " << filename; + if (rval && !QFile::rename(out.fileName(), filename)) { + qWarning() << "could not rename " << out.fileName() << " to " << filename; rval = false; } } From 906a89c16d565df3614f3da5ead2a1091a005076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 8 Dec 2017 23:55:59 +0000 Subject: [PATCH 003/175] Use ExternalCommand to copy fstab file to its final location. --- src/core/fstab.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index 756a147..2a5fb69 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -18,6 +18,7 @@ *************************************************************************/ #include "core/fstab.h" +#include "util/externalcommand.h" #include @@ -179,32 +180,32 @@ static void writeEntry(QFile& output, const FstabEntry& entry) bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename) { - bool rval = true; QTemporaryFile out; out.setAutoRemove(false); if (!out.open()) { qWarning() << "could not open output file " << out.fileName(); - rval = false; + return false; } else { for (const auto &e : fstabEntries) writeEntry(out, e); out.close(); - const QString bakFilename = QStringLiteral("%1.bak").arg(filename); - QFile::remove(bakFilename); + ExternalCommand mvCmd(QStringLiteral("mv"), { filename, bakFilename } ); - if (QFile::exists(filename) && !QFile::rename(filename, bakFilename)) { - qWarning() << "could not rename " << filename << " to " << bakFilename; - rval = false; + if ( !(mvCmd.run(-1) && mvCmd.exitCode() == 0) ) { + qWarning() << "could not backup " << filename << " to " << bakFilename; + return false; } - if (rval && !QFile::rename(out.fileName(), filename)) { - qWarning() << "could not rename " << out.fileName() << " to " << filename; - rval = false; + ExternalCommand mvCmd2(QStringLiteral("mv"), { out.fileName(), filename } ); + + if ( !(mvCmd2.run(-1) && mvCmd2.exitCode() == 0) ) { + qWarning() << "could not move " << out.fileName() << " to " << filename; + return false; } } - return rval; + return true; } From 192305c1d506cf6d84549c27f2a96b1f6dcf5e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 9 Dec 2017 18:11:04 +0000 Subject: [PATCH 004/175] Close write channel after writing to QProcess. --- src/util/externalcommandhelper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index c60d84c..30a719b 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -32,6 +32,7 @@ ActionReply ExternalCommandHelper::start(const QVariantMap& args) cmd.setEnvironment(environment); cmd.start(command, arguments); cmd.write(input); + cmd.closeWriteChannel(); cmd.waitForFinished(-1); QByteArray output = cmd.readAllStandardOutput(); reply.addData(QStringLiteral("output"), output); From 4cc07d2366d8686f67c64a6f725fc9993925e39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 10 Dec 2017 17:37:10 +0000 Subject: [PATCH 005/175] Adapt ntfs updateBootSector changes to kauth branch. --- src/fs/ntfs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index f925127..f068624 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -190,11 +190,11 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const 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()) { Log() << xi18nc("@info:progress", "Could not write new start sector to partition %1 when trying to update the NTFS boot sector.", deviceNode); return false; } - cmd.write(QByteArray(s, sizeof(s))); cmd.waitFor(-1); // Also update backup NTFS boot sector located at the end of the partition @@ -202,11 +202,11 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const 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()) { Log() << xi18nc("@info:progress", "Could not write new start sector to partition %1 when trying to update the NTFS boot sector.", deviceNode); return false; } - cmd2.write(QByteArray(s, sizeof(s))); cmd2.waitFor(-1); Log() << xi18nc("@info:progress", "Updated NTFS boot sector for partition %1 successfully.", deviceNode); From 27462bcddb2500769751352c48cbe305d3ce2be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 10 Dec 2017 18:08:28 +0000 Subject: [PATCH 006/175] Remove workaround to access user dbus session as root. --- src/core/operationrunner.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/core/operationrunner.cpp b/src/core/operationrunner.cpp index 01771c7..092e8f4 100644 --- a/src/core/operationrunner.cpp +++ b/src/core/operationrunner.cpp @@ -50,15 +50,6 @@ void OperationRunner::run() bool status = true; // Disable Plasma removable device automounting - unsigned int currentUid = getuid(); // 0 if running as root - char *login = getlogin(); - if (login != nullptr){ - passwd* pwnam = getpwnam(login); - if (pwnam != nullptr) { - unsigned int userId = pwnam->pw_uid; // uid of original user before sudo - seteuid(userId); - } - } QStringList modules; QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus")); QDBusInterface kdedInterface( QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5"), bus ); @@ -69,7 +60,6 @@ void OperationRunner::run() bool automounter = modules.contains(automounterService); if (automounter) kdedInterface.call( QStringLiteral("unloadModule"), automounterService ); - seteuid(currentUid); for (int i = 0; i < numOperations(); i++) { suspendMutex().lock(); From 8264c87ab885b9e4589d28833d3d6d9fc5162340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 10 Dec 2017 18:44:54 +0000 Subject: [PATCH 007/175] Cleanup unnecessary includes. --- src/core/operationrunner.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/operationrunner.cpp b/src/core/operationrunner.cpp index 092e8f4..d24617b 100644 --- a/src/core/operationrunner.cpp +++ b/src/core/operationrunner.cpp @@ -25,9 +25,6 @@ #include #include -#include -#include - /** Constructs an OperationRunner. @param ostack the OperationStack to act on */ From fdf6e19de0ce8cb67a61ebdb784c363d84d1b1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 10 Dec 2017 19:56:04 +0000 Subject: [PATCH 008/175] Remove another workaround which hopefully is no longer necessary. --- src/jobs/checkfilesystemjob.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/jobs/checkfilesystemjob.cpp b/src/jobs/checkfilesystemjob.cpp index 866de6a..55110f2 100644 --- a/src/jobs/checkfilesystemjob.cpp +++ b/src/jobs/checkfilesystemjob.cpp @@ -48,15 +48,6 @@ bool CheckFileSystemJob::run(Report& parent) if (partition().fileSystem().supportCheck() == FileSystem::cmdSupportFileSystem) rval = partition().fileSystem().check(*report, partition().deviceNode()); - // HACK - // In rare cases after moving file system to a new location file system check - // fails on the first try. As a temporary workaround, wait a bit and try again. - if (!rval) { - QThread::sleep(2); - qDebug() << "Partition might not be ready yet. Retrying..."; - rval = partition().fileSystem().check(*report, partition().deviceNode()); - } - jobFinished(*report, rval); return rval; From 8177fb9738b985a3acdbcc574a751a763b2a8906 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 8 Jan 2018 17:59:48 -0300 Subject: [PATCH 009/175] Adding smart JSON output support --- src/core/CMakeLists.txt | 6 + src/core/smartattribute.cpp | 64 ++- src/core/smartattribute.h | 4 +- src/core/smartattributeparseddata.cpp | 653 ++++++++++++++++++++++++++ src/core/smartattributeparseddata.h | 207 ++++++++ src/core/smartdiskinformation.cpp | 194 ++++++++ src/core/smartdiskinformation.h | 192 ++++++++ src/core/smartparser.cpp | 159 +++++++ src/core/smartparser.h | 57 +++ src/core/smartstatus.cpp | 236 ++++------ src/core/smartstatus.h | 78 +-- 11 files changed, 1654 insertions(+), 196 deletions(-) create mode 100644 src/core/smartattributeparseddata.cpp create mode 100644 src/core/smartattributeparseddata.h create mode 100644 src/core/smartdiskinformation.cpp create mode 100644 src/core/smartdiskinformation.h create mode 100644 src/core/smartparser.cpp create mode 100644 src/core/smartparser.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bb5fb6b..584c8b4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -20,6 +20,9 @@ set(CORE_SRC core/partitiontable.cpp core/smartstatus.cpp core/smartattribute.cpp + core/smartparser.cpp + core/smartattributeparseddata.cpp + core/smartdiskinformation.cpp core/volumemanagerdevice.cpp ) @@ -38,6 +41,9 @@ set(CORE_LIB_HDRS core/partitiontable.h core/smartattribute.h core/smartstatus.h + core/smartparser.h + core/smartattributeparseddata.h + core/smartdiskinformation.h core/volumemanagerdevice.h ) diff --git a/src/core/smartattribute.cpp b/src/core/smartattribute.cpp index 0346bcb..50593d1 100644 --- a/src/core/smartattribute.cpp +++ b/src/core/smartattribute.cpp @@ -18,33 +18,33 @@ #include "core/smartattribute.h" #include "core/smartstatus.h" +#include "core/smartattributeparseddata.h" #include #include #include -#include - static QString getAttrName(qint32 id); static QString getAttrDescription(qint32 id); static QString getPrettyValue(quint64 value, qint64 unit); -static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a); -static QString getRaw(const uint8_t*); +static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a); +static QString getRaw(quint64 raw); -SmartAttribute::SmartAttribute(const SkSmartAttributeParsedData* a) : - m_Id(a->id), - m_Name(getAttrName(a->id)), - m_Desc(getAttrDescription(a->id)), - m_FailureType(a->prefailure ? PreFailure : OldAge), - m_UpdateType(a->online ? Online : Offline), - m_Current(a->current_value_valid ? a->current_value : -1), - m_Worst(a->worst_value_valid ? a->worst_value : -1), - m_Threshold(a->threshold_valid ? a->threshold : -1), - m_Raw(getRaw(a->raw)), +SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) : + m_Id(a.id()), + m_Name(getAttrName(a.id())), + m_Desc(getAttrDescription(a.id())), + m_FailureType(a.prefailure() ? PreFailure : OldAge), + m_UpdateType(a.online() ? Online : Offline), + m_Current(a.currentValueValid() ? a.currentValue() : -1), + m_Worst(a.worstValueValid() ? a.worstValue() : -1), + m_Threshold(a.thresholdValid() ? a.threshold() : -1), + m_Raw(getRaw(a.raw())), m_Assessment(getAssessment(a)), - m_Value(getPrettyValue(a->pretty_value, a->pretty_unit)) + m_Value(getPrettyValue(a.prettyValue(), a.prettyUnit())) { + } QString SmartAttribute::assessmentToString(Assessment a) @@ -73,23 +73,23 @@ static QString getPrettyValue(quint64 value, qint64 unit) QString rval; switch (unit) { - case SK_SMART_ATTRIBUTE_UNIT_MSECONDS: + case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS: rval = KFormat().formatDuration(value); break; - case SK_SMART_ATTRIBUTE_UNIT_SECTORS: + case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS: rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value); break; - case SK_SMART_ATTRIBUTE_UNIT_MKELVIN: + case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN: rval = SmartStatus::tempToString(value); break; - case SK_SMART_ATTRIBUTE_UNIT_NONE: + case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE: rval = QLocale().toString(value); break; - case SK_SMART_ATTRIBUTE_UNIT_UNKNOWN: + case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN: default: rval = xi18nc("@item:intable not applicable", "N/A"); break; @@ -214,23 +214,23 @@ static QString getAttrDescription(qint32 id) return QString(); } -static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData* a) +static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a) { SmartAttribute::Assessment rval = SmartAttribute::NotApplicable; bool failed = false; bool hasFailed = false; - if (a->prefailure) { - if (a->good_now_valid && !a->good_now) + if (a.prefailure()) { + if (a.goodNowValid() && !a.goodNow()) failed = true; - if (a->good_in_the_past_valid && !a->good_in_the_past) + if (a.goodInThePastValid() && !a.goodInThePast()) hasFailed = true; - } else if (a->threshold_valid) { - if (a->current_value_valid && a->current_value <= a->threshold) + } else if (a.thresholdValid()) { + if (a.currentValueValid() && a.currentValue() <= a.threshold()) failed = true; - else if (a->worst_value_valid && a->worst_value <= a->threshold) + else if (a.worstValueValid() && a.worstValue() <= a.threshold()) hasFailed = true; } @@ -238,19 +238,17 @@ static SmartAttribute::Assessment getAssessment(const SkSmartAttributeParsedData rval = SmartAttribute::Failing; else if (hasFailed) rval = SmartAttribute::HasFailed; - else if (a->warn) + else if (a.warn()) rval = SmartAttribute::Warning; - else if (a->good_now_valid) + else if (a.goodNowValid()) rval = SmartAttribute::Good; return rval; } -static QString getRaw(const uint8_t* raw) +static QString getRaw(quint64 raw) { QString rval = QStringLiteral("0x"); - for (qint32 i = 5; i >= 0; i--) - rval += QStringLiteral("%1").arg(raw[i], 2, 16, QLatin1Char('0')); - + rval += QStringLiteral("%1").arg(raw, 12, 16, QLatin1Char('0')); return rval; } diff --git a/src/core/smartattribute.h b/src/core/smartattribute.h index 226e6eb..d0d2e2a 100644 --- a/src/core/smartattribute.h +++ b/src/core/smartattribute.h @@ -20,10 +20,10 @@ #define KPMCORE_SMARTATTRIBUTE_H #include "util/libpartitionmanagerexport.h" +#include "core/smartattributeparseddata.h" #include -struct SkSmartAttributeParsedData; class LIBKPMCORE_EXPORT SmartAttribute { @@ -47,7 +47,7 @@ public: }; public: - SmartAttribute(const SkSmartAttributeParsedData* a); + SmartAttribute(const SmartAttributeParsedData& a); public: qint32 id() const { diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp new file mode 100644 index 0000000..8960c92 --- /dev/null +++ b/src/core/smartattributeparseddata.cpp @@ -0,0 +1,653 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "smartattributeparseddata.h" +#include "core/smartdiskinformation.h" + +#include +#include +#include + +#define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL)) +#define MKELVIN_VALID_MAX ((qint64) ((100LL*1000LL) + 273150LL)) + +#define MSECOND_VALID_MIN 1ULL +#define MSECOND_VALID_SHORT_MAX (60ULL * 60ULL * 1000ULL) +#define MSECOND_VALID_LONG_MAX (30ULL * 365ULL * 24ULL * 60ULL * 60ULL * 1000ULL) + +static const QMap tableUnit(); +static SmartAttributeParsedData::SmartQuirk *getQuirk(QString model, QString firmware); + +SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, + QJsonObject jsonAttribute) : + m_Id(0), + m_CurrentValue(0), + m_WorstValue(0), + m_Threshold(0), + m_Raw(0), + m_PrettyValue(0), + m_CurrentValueValid(false), + m_WorstValueValid(false), + m_ThresholdValid(false), + m_Prefailure(false), + m_Online(false), + m_GoodNow(true), + m_GoodNowValid(false), + m_GoodInThePast(true), + m_GoodInThePastValid(false), + m_Warn(false), + m_PrettyUnit(SMART_ATTRIBUTE_UNIT_UNKNOWN), + m_Disk(disk), + m_Quirk(nullptr) +{ + if (disk) + m_Quirk = getQuirk(disk->model(), disk->firmware()); + + if (!jsonAttribute.isEmpty()) { + QString id = QString::fromLocal8Bit("id"); + QString value = QString::fromLocal8Bit("value"); + QString worst = QString::fromLocal8Bit("worst"); + QString thresh = QString::fromLocal8Bit("thresh"); + QString raw = QString::fromLocal8Bit("raw"); + QString str = QString::fromLocal8Bit("string"); + QString flags = QString::fromLocal8Bit("flags"); + QString prefailure = QString::fromLocal8Bit("prefailure"); + QString online = QString::fromLocal8Bit("updated_online"); + + m_Id = jsonAttribute[id].toInt(); + m_CurrentValue = jsonAttribute[value].toInt(); + m_WorstValue = jsonAttribute[worst].toInt(); + m_Threshold = jsonAttribute[thresh].toInt(); + + QJsonObject rawObj = jsonAttribute[raw].toObject(); + + m_Raw = rawObj[str].toString().toULongLong(); + + QJsonObject flagsObj = jsonAttribute[flags].toObject(); + + m_Prefailure = flagsObj[prefailure].toBool(); + m_Online = flagsObj[online].toBool(); + + if (!updateUnit()) + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + + makePretty(); + + validateValues(); + + verifyAttribute(); + } +} + +SmartAttributeParsedData::SmartAttributeParsedData(const SmartAttributeParsedData &other) : + m_Id(other.id()), + m_CurrentValue(other.currentValue()), + m_WorstValue(other.worstValue()), + m_Threshold(other.threshold()), + m_Raw(other.raw()), + m_PrettyValue(other.prettyValue()), + m_CurrentValueValid(other.currentValueValid()), + m_WorstValueValid(other.worstValueValid()), + m_ThresholdValid(other.thresholdValid()), + m_Prefailure(other.prefailure()), + m_Online(other.online()), + m_GoodNow(other.goodNow()), + m_GoodNowValid(other.goodNowValid()), + m_GoodInThePast(other.goodInThePast()), + m_GoodInThePastValid(other.goodInThePastValid()), + m_Warn(other.warn()), + m_PrettyUnit(other.prettyUnit()), + m_Disk(other.disk()), + m_Quirk(other.m_Quirk) +{ + +} + +void SmartAttributeParsedData::validateValues() +{ + m_CurrentValueValid = m_CurrentValue >= 1 && m_CurrentValue <= 0xFD; + m_WorstValueValid = m_WorstValue >= 1 && m_WorstValue <= 0xFD; + m_ThresholdValid = m_Threshold != 0xFE; + + if (m_Threshold >= 1 && m_Threshold <= 0xFD) { + if (m_WorstValueValid) { + m_GoodInThePast = m_GoodInThePast && (m_WorstValue > m_Threshold); + m_GoodInThePastValid = true; + } + if (m_CurrentValueValid) { + m_GoodNow = m_GoodNow && (m_CurrentValue > m_Threshold); + m_GoodNowValid = true; + } + } + + m_Warn = (m_GoodNowValid && !m_GoodNow) || (m_GoodInThePastValid && !m_GoodInThePast); +} + +void SmartAttributeParsedData::makePretty() +{ + if (m_PrettyUnit == SMART_ATTRIBUTE_UNIT_UNKNOWN) + return; + + switch (id()) { + case 3: + m_PrettyValue = raw() & 0xFFFF; + break; + + case 5: + m_PrettyValue = raw() & 0xFFFFFFFFU; + break; + + case 9: + m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000; + break; + + case 170: + m_PrettyValue = currentValue(); + break; + + case 190: + m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150; + break; + + case 194: + m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150; + break; + + case 197: + m_PrettyValue = (raw() & 0xFFFFFFFFU); + break; + + case 222: + m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000; + break; + + case 228: + m_PrettyValue = raw() * 60 * 1000; + break; + + case 231: + m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150; + break; + + case 232: + m_PrettyValue = currentValue(); + break; + + case 240: + m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000; + break; + + case 241: + m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL; + break; + + case 242: + m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL; + break; + + default: + m_PrettyValue = raw(); + break; + + } +} + +void SmartAttributeParsedData::verifyAttribute() +{ + if (id() == 3 || id() == 226) + verifyShortTime(); + else if (id() == 5 || id() == 187 || id() == 197 || id() == 198) + verifySectors(); + else if (id() == 9 || id() == 222 || id() == 240) + verifyLongTime(); + else if (id() == 190 || id() == 194 || id() == 231) + verifyTemperature(); +} + +void SmartAttributeParsedData::verifyTemperature() +{ + if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MKELVIN) + return; + + if (prettyValue() < MKELVIN_VALID_MIN || prettyValue() > MKELVIN_VALID_MAX) + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; +} + +void SmartAttributeParsedData::verifyShortTime() +{ + if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MSECONDS) + return; + + if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_SHORT_MAX) + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; +} + +void SmartAttributeParsedData::verifyLongTime() +{ + if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MSECONDS) + return; + + if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_LONG_MAX) + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; +} + +void SmartAttributeParsedData::verifySectors() +{ + if (prettyUnit() != SMART_ATTRIBUTE_UNIT_SECTORS) + return; + + quint64 maxSectors = disk()->size() / 512ULL; + + if (prettyValue() == 0xFFFFFFFFULL || prettyValue() == 0xFFFFFFFFFFFFULL || (maxSectors > 0 + && prettyValue() > maxSectors)) + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + else if ((id() == 5 || id() == 197) && prettyValue() > 0) + m_Warn = true; +} + +bool SmartAttributeParsedData::updateUnit() +{ + if (m_Quirk) { + switch (id()) { + case 3: + if (*m_Quirk & SMART_QUIRK_3_UNUSED) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + return true; + } + break; + + case 4: + if (*m_Quirk & SMART_QUIRK_4_UNUSED) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + return true; + } + break; + + case 5: + if (*m_Quirk & SMART_QUIRK_5_UNKNOWN) + return false; + break; + + case 9: + if (*m_Quirk & SMART_QUIRK_9_POWERONMINUTES) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + return true; + } else if (*m_Quirk & SMART_QUIRK_9_POWERONSECONDS) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + return true; + } else if (*m_Quirk & SMART_QUIRK_9_POWERONHALFMINUTES) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + return true; + } else if (*m_Quirk & SMART_QUIRK_9_UNKNOWN) + return false; + break; + + case 190: + if (*m_Quirk & SMART_QUIRK_190_UNKNOWN) + return false; + break; + + case 192: + if (*m_Quirk & SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + return true; + } + break; + + case 194: + if (*m_Quirk & SMART_QUIRK_194_10XCELSIUS) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MKELVIN; + return true; + } else if (*m_Quirk & SMART_QUIRK_194_UNKNOWN) + return false; + break; + + case 197: + if (*m_Quirk & SMART_QUIRK_197_UNKNOWN) + return false; + break; + + case 198: + if (*m_Quirk & SMART_QUIRK_198_UNKNOWN) + return false; + break; + + case 200: + if (*m_Quirk & SMART_QUIRK_200_WRITEERRORCOUNT) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + return true; + } + break; + + case 201: + if (*m_Quirk & SMART_QUIRK_201_DETECTEDTACOUNT) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + return true; + } + break; + + case 225: + if (*m_Quirk & SMART_QUIRK_225_TOTALLBASWRITTEN) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MB; + return true; + } + break; + + case 226: + if (*m_Quirk & SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; + return true; + } + break; + + case 227: + if (*m_Quirk & SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; + return true; + } + break; + + case 228: + if (*m_Quirk & SMART_QUIRK_228_WORKLOADTIMER) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + return true; + } + break; + + case 232: + if (*m_Quirk & SMART_QUIRK_232_AVAILABLERESERVEDSPACE) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; + return true; + } + break; + + case 233: + if (*m_Quirk & SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) { + m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; + return true; + } + break; + + } + } + + if (tableUnit().contains(id())) { + m_PrettyUnit = tableUnit()[id()]; + return true; + } + + return false; +} + +static const QMap tableUnit() +{ + QMap table; + table.insert(1, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(2, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(3, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); + table.insert(4, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(5, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); + table.insert(6, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(7, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(8, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(9, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); + table.insert(10, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(11, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(12, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(13, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(170, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_PERCENT); + table.insert(171, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(172, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(175, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(176, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(177, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(178, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(179, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(180, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(181, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(182, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(183, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(184, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(187, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); + table.insert(188, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(189, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(190, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); + table.insert(191, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(192, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(193, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(194, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); + table.insert(195, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(196, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(197, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); + table.insert(198, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); + table.insert(199, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(200, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(201, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(202, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(203, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(204, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(205, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(206, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(207, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(208, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(209, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(220, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(221, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(222, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); + table.insert(223, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(224, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(225, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(226, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); + table.insert(227, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(228, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + table.insert(230, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(231, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); + table.insert(232, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_PERCENT); + table.insert(233, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(234, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); + table.insert(235, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); + table.insert(240, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); + table.insert(241, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MB); + table.insert(242, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MB); + table.insert(250, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + + return table; +} + +static const SmartAttributeParsedData::SmartQuirkDataBase *quirkDatabase() +{ + static const SmartAttributeParsedData::SmartQuirkDataBase quirkDb[] = { + { + "^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$", + "^0085000B$", + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_197_UNKNOWN | + SmartAttributeParsedData::SMART_QUIRK_198_UNKNOWN) + }, + { + "^FUJITSU MHR2040AT$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | + SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT) + }, + { + "^FUJITSU MHS20[6432]0AT( .)?$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | + SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT | + SmartAttributeParsedData::SMART_QUIRK_201_DETECTEDTACOUNT) + }, + { + "^(" + "FUJITSU M1623TAU|" + "FUJITSU MHG2...ATU?.*|" + "FUJITSU MHH2...ATU?.*|" + "FUJITSU MHJ2...ATU?.*|" + "FUJITSU MHK2...ATU?.*|" + "FUJITSU MHL2300AT|" + "FUJITSU MHM2(20|15|10|06)0AT|" + "FUJITSU MHN2...AT|" + "FUJITSU MHR2020AT|" + "FUJITSU MHT2...(AH|AS|AT|BH)U?.*|" + "FUJITSU MHU2...ATU?.*|" + "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*|" + "FUJITSU MP[A-G]3...A[HTEV]U?.*" + ")$", + NULL, + SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS + }, + { + "^(" + "SAMSUNG SV4012H|" + "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]" + ")$", + NULL, + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES + }, + { + "^(" + "SAMSUNG SV0412H|" + "SAMSUNG SV1204H" + ")$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES | + SmartAttributeParsedData::SMART_QUIRK_194_10XCELSIUS) + }, + { + "^SAMSUNG SP40A2H$", + "^RR100-07$", + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES + }, + { + "^SAMSUNG SP80A4H$", + "^RT100-06$", + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES + }, + { + "^SAMSUNG SP8004H$", + "^QW100-61$", + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES + }, + { + "^(" + "Maxtor 2B0(0[468]|1[05]|20)H1|" + "Maxtor 4G(120J6|160J[68])|" + "Maxtor 4D0(20H1|40H2|60H3|80H4)" + ")$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_194_UNKNOWN) + }, + { + "^(" + "Maxtor 2F0[234]0[JL]0|" + "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|" + "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)|" + "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)|" + "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)|" + "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)|" + "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)|" + "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)|" + "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)|" + "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)|" + "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)|" + "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)|" + "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)|" + "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)|" + "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)|" + "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?|" + "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)|" + "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)|" + "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)|" + "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)|" + "Maxtor (98196H8|96147H6)|" + "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)|" + "Maxtor 6(E0[234]|K04)0L0|" + "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0|" + "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)|" + "Maxtor 7Y250[PM]0|" + "Maxtor [45]A(25|30|32)0[JN]0|" + "Maxtor 7L(25|30)0[SR]0" + ")$", + NULL, + SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES + }, + { + "^(" + "HITACHI_DK14FA-20B|" + "HITACHI_DK23..-..B?|" + "HITACHI_DK23FA-20J|HTA422020F9AT[JN]0|" + "HE[JN]4230[23]0F9AT00|" + "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00" + ")$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_193_LOADUNLOAD) + }, + { + "^HTS541010G9SA00$", + "^MBZOC60P$", + SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN + }, + { + "^MCCOE64GEMPP$", + "^2.9.0[3-9]$", + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN | + SmartAttributeParsedData::SMART_QUIRK_190_UNKNOWN) + }, + { + "^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$", + NULL, + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_3_UNUSED | + SmartAttributeParsedData::SMART_QUIRK_4_UNUSED | + SmartAttributeParsedData::SMART_QUIRK_225_TOTALLBASWRITTEN | + SmartAttributeParsedData::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR | + SmartAttributeParsedData::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS | + SmartAttributeParsedData::SMART_QUIRK_228_WORKLOADTIMER | + SmartAttributeParsedData::SMART_QUIRK_232_AVAILABLERESERVEDSPACE | + SmartAttributeParsedData::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) + } + }; + + return quirkDb; +} + +static SmartAttributeParsedData::SmartQuirk *getQuirk(QString model, QString firmware) +{ + const SmartAttributeParsedData::SmartQuirkDataBase *db; + + QRegExp modelRegex; + QRegExp firmwareRegex; + + for (db = quirkDatabase(); db->model || db->firmware; db++) { + if (db->model) { + modelRegex.setPattern(QString::fromLocal8Bit(db->model)); + if (!modelRegex.exactMatch(model)) + continue; + } + if (db->firmware) { + firmwareRegex.setPattern(QString::fromLocal8Bit(db->firmware)); + if (!firmwareRegex.exactMatch(firmware)) + continue; + } + return (SmartAttributeParsedData::SmartQuirk *)&db->quirk; + } + + return nullptr; +} diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h new file mode 100644 index 0000000..641b5ea --- /dev/null +++ b/src/core/smartattributeparseddata.h @@ -0,0 +1,207 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#if !defined(KPMCORE_SMARTATTRIBUTEPARSEDDATA_H) +#define KPMCORE_SMARTATTRIBUTEPARSEDDATA_H + +#include +#include + +class SmartDiskInformation; + +class SmartAttributeParsedData +{ +public: + enum SmartAttributeUnit { + SMART_ATTRIBUTE_UNIT_UNKNOWN, + SMART_ATTRIBUTE_UNIT_NONE, + SMART_ATTRIBUTE_UNIT_MSECONDS, + SMART_ATTRIBUTE_UNIT_SECTORS, + SMART_ATTRIBUTE_UNIT_MKELVIN, + SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, + SMART_ATTRIBUTE_UNIT_PERCENT, + SMART_ATTRIBUTE_UNIT_MB, + _SMART_ATTRIBUTE_UNIT_MAX + }; + + enum SmartQuirk { + SMART_QUIRK_9_POWERONMINUTES = 0x000001, + SMART_QUIRK_9_POWERONSECONDS = 0x000002, + SMART_QUIRK_9_POWERONHALFMINUTES = 0x000004, + SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x000008, + SMART_QUIRK_193_LOADUNLOAD = 0x000010, + SMART_QUIRK_194_10XCELSIUS = 0x000020, + SMART_QUIRK_194_UNKNOWN = 0x000040, + SMART_QUIRK_200_WRITEERRORCOUNT = 0x000080, + SMART_QUIRK_201_DETECTEDTACOUNT = 0x000100, + SMART_QUIRK_5_UNKNOWN = 0x000200, + SMART_QUIRK_9_UNKNOWN = 0x000400, + SMART_QUIRK_197_UNKNOWN = 0x000800, + SMART_QUIRK_198_UNKNOWN = 0x001000, + SMART_QUIRK_190_UNKNOWN = 0x002000, + SMART_QUIRK_232_AVAILABLERESERVEDSPACE = 0x004000, + SMART_QUIRK_233_MEDIAWEAROUTINDICATOR = 0x008000, + SMART_QUIRK_225_TOTALLBASWRITTEN = 0x010000, + SMART_QUIRK_4_UNUSED = 0x020000, + SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR = 0x040000, + SMART_QUIRK_227_TIMEWORKLOADHOSTREADS = 0x080000, + SMART_QUIRK_228_WORKLOADTIMER = 0x100000, + SMART_QUIRK_3_UNUSED = 0x200000 + }; + + struct SmartQuirkDataBase { + const char *model; + const char *firmware; + SmartAttributeParsedData::SmartQuirk quirk; + }; + +public: + SmartAttributeParsedData(SmartDiskInformation *disk, QJsonObject jsonAttribute); + + SmartAttributeParsedData(const SmartAttributeParsedData &other); + +public: + quint32 id() const + { + return m_Id; + } + + qint32 currentValue() const + { + return m_CurrentValue; + } + + qint32 worstValue() const + { + return m_WorstValue; + } + + qint32 threshold() const + { + return m_Threshold; + } + + bool prefailure() const + { + return m_Prefailure; + } + + bool online() const + { + return m_Online; + } + + quint64 raw() const + { + return m_Raw; + } + + quint64 prettyValue() const + { + return m_PrettyValue; + } + + SmartAttributeUnit prettyUnit() const + { + return m_PrettyUnit; + } + + bool goodNowValid() const + { + return m_GoodNowValid; + } + + bool goodNow() const + { + return m_GoodNow; + } + + bool goodInThePastValid() const + { + return m_GoodInThePastValid; + } + + bool goodInThePast() const + { + return m_GoodInThePast; + } + + bool thresholdValid() const + { + return m_ThresholdValid; + } + + bool currentValueValid() const + { + return m_CurrentValueValid; + } + + bool worstValueValid() const + { + return m_WorstValueValid; + } + + bool warn() const + { + return m_Warn; + } + + SmartDiskInformation *disk() const + { + return m_Disk; + } + +protected: + void validateValues(); + + bool updateUnit(); + + void makePretty(); + + void verifyAttribute(); + + void verifyTemperature(); + + void verifyShortTime(); + + void verifyLongTime(); + + void verifySectors(); + +private: + quint32 m_Id; + qint32 m_CurrentValue; + qint32 m_WorstValue; + qint32 m_Threshold; + quint64 m_Raw; + quint64 m_PrettyValue; + bool m_CurrentValueValid; + bool m_WorstValueValid; + bool m_ThresholdValid; + bool m_Prefailure; + bool m_Online; + bool m_GoodNow; + bool m_GoodNowValid; + bool m_GoodInThePast; + bool m_GoodInThePastValid; + bool m_Warn; + SmartAttributeUnit m_PrettyUnit; + SmartDiskInformation *m_Disk; + SmartQuirk *m_Quirk; +}; + +#endif // SMARTATTRIBUTEPARSEDDATA_H diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp new file mode 100644 index 0000000..cf701ef --- /dev/null +++ b/src/core/smartdiskinformation.cpp @@ -0,0 +1,194 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "core/smartdiskinformation.h" +#include "core/smartattributeparseddata.h" + +static quint64 u64log2(quint64 n); + +SmartDiskInformation::SmartDiskInformation() : + m_ModelName(QString()), + m_FirmwareVersion(QString()), + m_SerialNumber(QString()), + m_Size(0), + m_Temperature(0), + m_BadSectors(0), + m_PoweredOn(0), + m_PowerCycles(0), + m_SmartStatus(false), + m_BadAttributeNow(false), + m_BadAttributeInThePast(false), + m_SelfTestExecutionStatus(SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER), + m_Overall(SmartDiskInformation::SMART_OVERALL_BAD_STATUS) +{ + +} + +void SmartDiskInformation::updateBadSectors() +{ + SmartAttributeParsedData *reallocatedSectorCt; + reallocatedSectorCt = findAttribute(5); + + SmartAttributeParsedData *currentPendingSector; + currentPendingSector = findAttribute(197); + + if (!reallocatedSectorCt && !currentPendingSector) + m_BadSectors = 0; + else if (reallocatedSectorCt && currentPendingSector) + m_BadSectors = reallocatedSectorCt->prettyValue() + currentPendingSector->prettyValue(); + else if (reallocatedSectorCt) + m_BadSectors = reallocatedSectorCt->prettyValue(); + else + m_BadSectors = currentPendingSector->prettyValue(); +} + +void SmartDiskInformation::updateOverall() +{ + if (!smartStatus()) { + m_Overall = SMART_OVERALL_BAD_STATUS; + return; + } + + quint64 sector_threshold = u64log2(size() / 512) * 1024; + + if (badSectors() >= sector_threshold) { + m_Overall = SMART_OVERALL_BAD_SECTOR_MANY; + return; + } + + validateBadAttributes(); + + if (m_BadAttributeNow) { + m_Overall = SMART_OVERALL_BAD_ATTRIBUTE_NOW; + return; + } + + if (badSectors() > 0) { + m_Overall = SMART_OVERALL_BAD_SECTOR; + return; + } + + if (m_BadAttributeInThePast) { + m_Overall = SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST; + return; + } + + m_Overall = SMART_OVERALL_GOOD; + +} + +bool SmartDiskInformation::updateTemperature() +{ + SmartAttributeParsedData *temperatureCelsius; + SmartAttributeParsedData *temperatureCelsius2; + SmartAttributeParsedData *airflowTemperatureCelsius; + + temperatureCelsius = findAttribute(231); + temperatureCelsius2 = findAttribute(194); + airflowTemperatureCelsius = findAttribute(190); + + if (temperatureCelsius != nullptr + && temperatureCelsius->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + m_Temperature = temperatureCelsius->prettyValue(); + return true; + } else if (temperatureCelsius2 != nullptr + && temperatureCelsius2->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + m_Temperature = temperatureCelsius2->prettyValue(); + return true; + } else if (airflowTemperatureCelsius != nullptr + && airflowTemperatureCelsius->prettyUnit() == + SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + m_Temperature = airflowTemperatureCelsius->prettyValue(); + return true; + } + return false; +} + +bool SmartDiskInformation::updatePowerOn() +{ + SmartAttributeParsedData *powerOnHours; + SmartAttributeParsedData *powerOnSeconds; + + powerOnHours = findAttribute(9); + powerOnSeconds = findAttribute(233); + + if (powerOnHours != nullptr + && powerOnHours->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS) { + m_PoweredOn = powerOnHours->prettyValue(); + return true; + } else if (powerOnSeconds != nullptr + && powerOnSeconds->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS) { + m_PoweredOn = powerOnSeconds->prettyValue(); + return true; + } + return false; +} + +bool SmartDiskInformation::updatePowerCycle() +{ + SmartAttributeParsedData *powerCycleCount; + + powerCycleCount = findAttribute(12); + + if (powerCycleCount != nullptr + && powerCycleCount->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE) { + m_PowerCycles = powerCycleCount->prettyValue(); + return true; + } + return false; +} + +void SmartDiskInformation::validateBadAttributes() +{ + foreach (SmartAttributeParsedData attribute, m_Attributes) { + if (attribute.prefailure()) { + if (attribute.goodNowValid() && !attribute.goodNow()) + m_BadAttributeNow = true; + if (attribute.goodInThePastValid() && !attribute.goodInThePast()) + m_BadAttributeInThePast = true; + } + } +} + +SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id) +{ + SmartAttributeParsedData *attr = nullptr; + foreach (SmartAttributeParsedData attribute, m_Attributes) { + if (id == attribute.id()) { + attr = new SmartAttributeParsedData(attribute); + break; + } + } + return attr; +} + +static quint64 u64log2(quint64 n) +{ + quint64 r; + + if (n <= 1) + return 0; + + r = 0; + for (;;) { + n = n >> 1; + if (!n) + return r; + r++; + } + return 0; +} diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h new file mode 100644 index 0000000..9c9ba4f --- /dev/null +++ b/src/core/smartdiskinformation.h @@ -0,0 +1,192 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#if !defined(KPMCORE_SMARTDISKINFORMATION_H) +#define SMARTDISKINFORMATION_H + +#include +#include + +class SmartAttributeParsedData; + +class SmartDiskInformation +{ +public: + enum SmartSelfTestExecutionStatus { + SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER = 0, + SMART_SELF_TEST_EXECUTION_STATUS_ABORTED = 1, + SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED = 2, + SMART_SELF_TEST_EXECUTION_STATUS_FATAL = 3, + SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN = 4, + SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL = 5, + SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO = 6, + SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ = 7, + SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING = 8, + SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS = 15, + _SMART_SELF_TEST_EXECUTION_STATUS_MAX + }; + + enum SmartOverall { + SMART_OVERALL_GOOD, + SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST, + SMART_OVERALL_BAD_SECTOR, + SMART_OVERALL_BAD_ATTRIBUTE_NOW, + SMART_OVERALL_BAD_SECTOR_MANY, + SMART_OVERALL_BAD_STATUS, + _SMART_OVERALL_MAX + }; + +public: + SmartDiskInformation(); + +public: + void updateBadSectors(); + + void updateOverall(); + + bool updateTemperature(); + + bool updatePowerOn(); + + bool updatePowerCycle(); + + SmartAttributeParsedData *findAttribute(quint32 id); + +public: + const QString model() const + { + return m_ModelName; + } + + const QString firmware() const + { + return m_FirmwareVersion; + } + + const QString serial() const + { + return m_SerialNumber; + } + + quint64 size() const + { + return m_Size; + } + + bool smartStatus() const + { + return m_SmartStatus; + } + + SmartSelfTestExecutionStatus selfTestExecutionStatus() const + { + return m_SelfTestExecutionStatus; + } + + SmartOverall overall() const + { + return m_Overall; + } + + quint64 temperature() const + { + return m_Temperature; + } + + quint64 badSectors() const + { + return m_BadSectors; + } + + quint64 poweredOn() const + { + return m_PoweredOn; + } + + quint64 powerCycles() const + { + return m_PowerCycles; + } + + QList attributes() const + { + return m_Attributes; + } + +public: + void setModel(QString modelName) + { + m_ModelName = modelName; + } + + void setFirmware(QString firmware) + { + m_FirmwareVersion = firmware; + } + + void setSerial(QString serial) + { + m_SerialNumber = serial; + } + + void setSize(quint64 size) + { + m_Size = size; + } + + void setPowerCycles(quint64 powerCycleCt) + { + m_PowerCycles = powerCycleCt; + } + + void setSmartStatus(bool smartStatus) + { + m_SmartStatus = smartStatus; + } + + void setSelfTestExecutionStatus(SmartSelfTestExecutionStatus status) + { + m_SelfTestExecutionStatus = status; + } + + void addAttribute(SmartAttributeParsedData &attribute) + { + m_Attributes << attribute; + } + +protected: + void validateBadAttributes(); + +private: + QString m_ModelName; + QString m_FirmwareVersion; + QString m_SerialNumber; + quint64 m_Size; + quint64 m_Temperature; + quint64 m_BadSectors; + quint64 m_PoweredOn; + quint64 m_PowerCycles; + bool m_SmartStatus; + bool m_BadAttributeNow; + bool m_BadAttributeInThePast; + SmartSelfTestExecutionStatus m_SelfTestExecutionStatus; + SmartOverall m_Overall; + QList m_Attributes; + +}; + +#endif // SMARTDISKINFORMATION_H diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp new file mode 100644 index 0000000..81a8214 --- /dev/null +++ b/src/core/smartparser.cpp @@ -0,0 +1,159 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "core/smartparser.h" + +#include "core/smartattributeparseddata.h" +#include "core/smartdiskinformation.h" + +#include +#include +#include +#include +#include +#include + +SmartParser::SmartParser(const QString &device_path) : + m_DevicePath(device_path), + m_DiskInformation(nullptr) +{ + +} + +bool SmartParser::init() +{ + loadSmartOutput(); + + if (m_SmartOutput.isEmpty()) + return false; + + QJsonObject smartJson = m_SmartOutput.object(); + + QString model_name = QString::fromLocal8Bit("model_name"); + QString firmware = QString::fromLocal8Bit("firmware_version"); + QString serial_number = QString::fromLocal8Bit("serial_number"); + QString device = QString::fromLocal8Bit("device"); + QString smart_status = QString::fromLocal8Bit("smart_status"); + QString passed = QString::fromLocal8Bit("passed"); + QString self_test = QString::fromLocal8Bit("self_test"); + QString status = QString::fromLocal8Bit("status"); + QString value = QString::fromLocal8Bit("value"); + QString user_capacity = QString::fromLocal8Bit("user_capacity"); + + if (!smartJson.contains(device)) { + qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno); + return false; + } + + if (!smartJson.contains(smart_status)) { + qDebug() << "getting smart status failed for " << devicePath() << ": " << strerror(errno); + return false; + } + + if (!smartJson.contains(model_name) || !smartJson.contains(firmware) + || !smartJson.contains(serial_number)) { + qDebug() << "getting disk identification data failed for " << devicePath() << ": " << strerror( + errno); + return false; + } + + m_DiskInformation = new SmartDiskInformation(); + + QJsonObject smartStatus = smartJson[smart_status].toObject(); + + m_DiskInformation->setSmartStatus(smartStatus[passed].toBool()); + + m_DiskInformation->setModel(smartJson[model_name].toString()); + m_DiskInformation->setFirmware(smartJson[firmware].toString()); + m_DiskInformation->setSerial(smartJson[serial_number].toString()); + m_DiskInformation->setSize(smartJson[user_capacity].toString().toULongLong()); + + QJsonObject selfTest = smartJson[self_test].toObject(); + QJsonObject selfTestStatus = selfTest[status].toObject(); + + m_DiskInformation->setSelfTestExecutionStatus((SmartDiskInformation::SmartSelfTestExecutionStatus) + selfTestStatus[value].toInt()); + + loadAttributes(); + + m_DiskInformation->updateBadSectors(); + + m_DiskInformation->updateOverall(); + + if (!m_DiskInformation->updateTemperature()) + qDebug() << "getting temp failed for " << devicePath() << ": " << strerror(errno); + + if (!m_DiskInformation->updatePowerOn()) + qDebug() << "getting powered on time failed for " << devicePath() << ": " << strerror(errno); + + if (!m_DiskInformation->updatePowerCycle()) + qDebug() << "getting power cycles failed for " << devicePath() << ": " << strerror(errno); + + return true; +} + +void SmartParser::loadSmartOutput() +{ + if (m_SmartOutput.isEmpty()) { + QStringList args; + args.append(QString::fromLocal8Bit("--all")); + args.append(QString::fromLocal8Bit("-j")); + args.append(devicePath()); + + QProcess smartctl; + smartctl.start(QString::fromLocal8Bit("smartctl"), args); + + bool success = smartctl.waitForFinished(); + + if (!success || smartctl.exitStatus() == QProcess::CrashExit) { + qDebug() << "smartctl initialization failed for " << devicePath() << ": " << strerror(errno); + return; + } + + QByteArray output = smartctl.readAllStandardOutput(); + smartctl.close(); + + m_SmartOutput = QJsonDocument::fromJson(output); + } +} + +void SmartParser::loadAttributes() +{ + loadSmartOutput(); + + if (m_SmartOutput.isEmpty()) + return; + + QJsonObject smartJson = m_SmartOutput.object(); + + QString ata_smart_attributes = QString::fromLocal8Bit("ata_smart_attributes"); + QString table = QString::fromLocal8Bit("table"); + + QJsonObject ataSmartAttributes = smartJson[ata_smart_attributes].toObject(); + + QJsonArray attributeArray = ataSmartAttributes[table].toArray(); + + if (!m_DiskInformation) { + qDebug() << "error loading smart attributes for " << devicePath() << ": " << strerror(errno); + return; + } + + foreach (QJsonValue value, attributeArray) { + SmartAttributeParsedData parsedObject(m_DiskInformation, value.toObject()); + m_DiskInformation->addAttribute(parsedObject); + } +} diff --git a/src/core/smartparser.h b/src/core/smartparser.h new file mode 100644 index 0000000..7a199fa --- /dev/null +++ b/src/core/smartparser.h @@ -0,0 +1,57 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#if !defined(KPMCORE_SMARTPARSER_H) +#define KPMCORE_SMARTPARSER_H + +#include +#include + +class SmartDiskInformation; + +class SmartParser +{ +public: + SmartParser(const QString &device_path); + +public: + bool init(); + +public: + const QString &devicePath() const + { + return m_DevicePath; + } + + SmartDiskInformation *diskInformation() const + { + return m_DiskInformation; + } + +protected: + void loadSmartOutput(); + + void loadAttributes(); + +private: + const QString m_DevicePath; + QJsonDocument m_SmartOutput; + SmartDiskInformation *m_DiskInformation; + +}; + +#endif // SMARTPARSER_H diff --git a/src/core/smartstatus.cpp b/src/core/smartstatus.cpp index 8b1cb91..60c8d6e 100644 --- a/src/core/smartstatus.cpp +++ b/src/core/smartstatus.cpp @@ -18,16 +18,19 @@ #include "core/smartstatus.h" +#include "core/smartparser.h" +#include "core/smartdiskinformation.h" +#include "core/smartattributeparseddata.h" + #include #include #include #include -#include #include -SmartStatus::SmartStatus(const QString& device_path) : +SmartStatus::SmartStatus(const QString &device_path) : m_DevicePath(device_path), m_InitSuccess(false), m_Status(false), @@ -46,148 +49,110 @@ SmartStatus::SmartStatus(const QString& device_path) : void SmartStatus::update() { - SkDisk* skDisk = nullptr; - SkBool skSmartStatus = false; - uint64_t mkelvin = 0; - uint64_t skBadSectors = 0; - uint64_t skPoweredOn = 0; - uint64_t skPowerCycles = 0; + SmartParser parser(devicePath()); - if (sk_disk_open(devicePath().toLocal8Bit().constData(), &skDisk) < 0) { - qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno); + if (!parser.init()) { + qDebug() << "error during smart output parsing for " << devicePath() << ": " << strerror(errno); return; } - if (sk_disk_smart_status(skDisk, &skSmartStatus) < 0) { - qDebug() << "getting smart status failed for " << devicePath() << ": " << strerror(errno); - sk_disk_free(skDisk); + SmartDiskInformation *disk; + + disk = parser.diskInformation(); + + if (!disk) return; + + setStatus(disk->smartStatus()); + + setModelName(disk->model()); + + setFirmware(disk->firmware()); + + setSerial(disk->serial()); + + switch (disk->selfTestExecutionStatus()) { + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ABORTED: + setSelfTestStatus(Aborted); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED: + setSelfTestStatus(Interrupted); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_FATAL: + setSelfTestStatus(Fatal); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN: + setSelfTestStatus(ErrorUnknown); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL: + setSelfTestStatus(ErrorEletrical); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO: + setSelfTestStatus(ErrorServo); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ: + setSelfTestStatus(ErrorRead); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING: + setSelfTestStatus(ErrorHandling); + break; + + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS: + setSelfTestStatus(InProgress); + break; + + default: + case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER: + setSelfTestStatus(Success); + break; + } - setStatus(skSmartStatus); + switch (disk->overall()) { + case SmartDiskInformation::SMART_OVERALL_GOOD: + setOverall(Good); + break; + + case SmartDiskInformation::SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST: + setOverall(BadPast); + break; + + case SmartDiskInformation::SMART_OVERALL_BAD_SECTOR: + setOverall(BadSectors); + break; + + case SmartDiskInformation::SMART_OVERALL_BAD_ATTRIBUTE_NOW: + setOverall(BadNow); + break; + + case SmartDiskInformation::SMART_OVERALL_BAD_SECTOR_MANY: + setOverall(BadSectorsMany); + break; + + default: + case SmartDiskInformation::SMART_OVERALL_BAD_STATUS: + setOverall(Bad); + break; - if (sk_disk_smart_read_data(skDisk) < 0) { - qDebug() << "reading smart data failed for " << devicePath() << ": " << strerror(errno); - sk_disk_free(skDisk); - return; } - const SkIdentifyParsedData* skIdentify; + setTemp(disk->temperature()); - if (sk_disk_identify_parse(skDisk, &skIdentify) < 0) - qDebug() << "getting identify data failed for " << devicePath() << ": " << strerror(errno); - else { - setModelName(QString::fromLocal8Bit(skIdentify->model)); - setFirmware(QString::fromLocal8Bit(skIdentify->firmware)); - setSerial(QString::fromLocal8Bit(skIdentify->serial)); - } + setBadSectors(disk->badSectors()); - const SkSmartParsedData* skParsed; - if (sk_disk_smart_parse(skDisk, &skParsed) < 0) - qDebug() << "parsing disk smart data failed for " << devicePath() << ": " << strerror(errno); - else { - switch (skParsed->self_test_execution_status) { - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ABORTED: - setSelfTestStatus(Aborted); - break; + setPoweredOn(disk->poweredOn()); - case SK_SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED: - setSelfTestStatus(Interrupted); - break; + setPowerCycles(disk->powerCycles()); - case SK_SMART_SELF_TEST_EXECUTION_STATUS_FATAL: - setSelfTestStatus(Fatal); - break; + addAttributes(disk->attributes()); - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN: - setSelfTestStatus(ErrorUnknown); - break; - - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL: - setSelfTestStatus(ErrorEletrical); - break; - - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO: - setSelfTestStatus(ErrorServo); - break; - - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ: - setSelfTestStatus(ErrorRead); - break; - - case SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING: - setSelfTestStatus(ErrorHandling); - break; - - case SK_SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS: - setSelfTestStatus(InProgress); - break; - - default: - case SK_SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER: - setSelfTestStatus(Success); - break; - } - } - - SkSmartOverall overall; - - if (sk_disk_smart_get_overall(skDisk, &overall) < 0) - qDebug() << "getting status failed for " << devicePath() << ": " << strerror(errno); - else { - switch (overall) { - case SK_SMART_OVERALL_GOOD: - setOverall(Good); - break; - - case SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST: - setOverall(BadPast); - break; - - case SK_SMART_OVERALL_BAD_SECTOR: - setOverall(BadSectors); - break; - - case SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW: - setOverall(BadNow); - break; - - case SK_SMART_OVERALL_BAD_SECTOR_MANY: - setOverall(BadSectorsMany); - break; - - default: - case SK_SMART_OVERALL_BAD_STATUS: - setOverall(Bad); - break; - } - } - - if (sk_disk_smart_get_temperature(skDisk, &mkelvin) < 0) - qDebug() << "getting temp failed for " << devicePath() << ": " << strerror(errno); - else - setTemp(mkelvin); - - if (sk_disk_smart_get_bad(skDisk, &skBadSectors) < 0) - qDebug() << "getting bad sectors failed for " << devicePath() << ": " << strerror(errno); - else - setBadSectors(skBadSectors); - - if (sk_disk_smart_get_power_on(skDisk, &skPoweredOn) < 0) - qDebug() << "getting powered on time failed for " << devicePath() << ": " << strerror(errno); - else - setPoweredOn(skPoweredOn); - - if (sk_disk_smart_get_power_cycle(skDisk, &skPowerCycles) < 0) - qDebug() << "getting power cycles failed for " << devicePath() << ": " << strerror(errno); - else - setPowerCycles(skPowerCycles); - - m_Attributes.clear(); - - sk_disk_smart_parse_attributes(skDisk, callback, this); - - sk_disk_free(skDisk); setInitSuccess(true); } @@ -195,7 +160,8 @@ QString SmartStatus::tempToString(quint64 mkelvin) { const double celsius = (mkelvin - 273150.0) / 1000.0; const double fahrenheit = 9.0 * celsius / 5.0 + 32; - return xi18nc("@item:intable degrees in Celsius and Fahrenheit", "%1° C / %2° F", QLocale().toString(celsius, 1), QLocale().toString(fahrenheit, 1)); + return xi18nc("@item:intable degrees in Celsius and Fahrenheit", "%1° C / %2° F", + QLocale().toString(celsius, 1), QLocale().toString(fahrenheit, 1)); } QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s) @@ -260,11 +226,13 @@ QString SmartStatus::overallAssessmentToString(Overall o) } -void SmartStatus::callback(SkDisk*, const SkSmartAttributeParsedData* a, void* user_data) +void SmartStatus::addAttributes(QList attr) { - SmartStatus* self = reinterpret_cast(user_data); + m_Attributes.clear(); - SmartAttribute sm(a); - self->m_Attributes.append(sm); + foreach (SmartAttributeParsedData at, attr) { + SmartAttribute sm(at); + m_Attributes.append(sm); + } } diff --git a/src/core/smartstatus.h b/src/core/smartstatus.h index c68a0ca..2983582 100644 --- a/src/core/smartstatus.h +++ b/src/core/smartstatus.h @@ -58,92 +58,116 @@ public: typedef QList Attributes; public: - SmartStatus(const QString& device_path); + SmartStatus(const QString &device_path); public: void update(); - const QString& devicePath() const { + const QString &devicePath() const + { return m_DevicePath; } - bool isValid() const { + bool isValid() const + { return m_InitSuccess; } - bool status() const { + bool status() const + { return m_Status; } - const QString& modelName() const { + const QString &modelName() const + { return m_ModelName; } - const QString& serial() const { + const QString &serial() const + { return m_Serial; } - const QString& firmware() const { + const QString &firmware() const + { return m_Firmware; } - quint64 temp() const { + quint64 temp() const + { return m_Temp; } - quint64 badSectors() const { + quint64 badSectors() const + { return m_BadSectors; } - quint64 powerCycles() const { + quint64 powerCycles() const + { return m_PowerCycles; } - quint64 poweredOn() const { + quint64 poweredOn() const + { return m_PoweredOn; } - const Attributes& attributes() const { + const Attributes &attributes() const + { return m_Attributes; } - Overall overall() const { + Overall overall() const + { return m_Overall; } - SelfTestStatus selfTestStatus() const { + SelfTestStatus selfTestStatus() const + { return m_SelfTestStatus; } + void addAttributes(QList attr); + static QString tempToString(quint64 mkelvin); static QString overallAssessmentToString(Overall o); static QString selfTestStatusToString(SmartStatus::SelfTestStatus s); protected: - void setStatus(bool s) { + void setStatus(bool s) + { m_Status = s; } - void setModelName(const QString& name) { + void setModelName(const QString &name) + { m_ModelName = name; } - void setSerial(const QString& s) { + void setSerial(const QString &s) + { m_Serial = s; } - void setFirmware(const QString& f) { + void setFirmware(const QString &f) + { m_Firmware = f; } - void setTemp(quint64 t) { + void setTemp(quint64 t) + { m_Temp = t; } - void setInitSuccess(bool b) { + void setInitSuccess(bool b) + { m_InitSuccess = b; } - void setBadSectors(quint64 s) { + void setBadSectors(quint64 s) + { m_BadSectors = s; } - void setPowerCycles(quint64 p) { + void setPowerCycles(quint64 p) + { m_PowerCycles = p; } - void setPoweredOn(quint64 t) { + void setPoweredOn(quint64 t) + { m_PoweredOn = t; } - void setOverall(Overall o) { + void setOverall(Overall o) + { m_Overall = o; } - void setSelfTestStatus(SelfTestStatus s) { + void setSelfTestStatus(SelfTestStatus s) + { m_SelfTestStatus = s; } - static void callback(SkDisk* skDisk, const SkSmartAttributeParsedData* a, void* user_data); - private: const QString m_DevicePath; bool m_InitSuccess; From d71731141c23dac6474970de61ce32d77a4363b3 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 9 Jan 2018 01:35:59 -0300 Subject: [PATCH 010/175] - Changed m_Quirk variable in SmartAttributeParsedData to SmartQuirk value instead of reference - Changed smartctl call to use ExternalCommand class instead of QProcess - Changed Q_FOREACH to C++11 ranged based for - Changed quint64 json parsing --- src/core/smartattributeparseddata.cpp | 56 +++++++++++++-------------- src/core/smartattributeparseddata.h | 2 +- src/core/smartdiskinformation.cpp | 4 +- src/core/smartparser.cpp | 24 +++++------- src/core/smartstatus.cpp | 2 +- 5 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index 8960c92..3b21ccd 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL)) #define MKELVIN_VALID_MAX ((qint64) ((100LL*1000LL) + 273150LL)) @@ -30,7 +31,7 @@ #define MSECOND_VALID_LONG_MAX (30ULL * 365ULL * 24ULL * 60ULL * 60ULL * 1000ULL) static const QMap tableUnit(); -static SmartAttributeParsedData::SmartQuirk *getQuirk(QString model, QString firmware); +static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware); SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, QJsonObject jsonAttribute) : @@ -52,7 +53,7 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, m_Warn(false), m_PrettyUnit(SMART_ATTRIBUTE_UNIT_UNKNOWN), m_Disk(disk), - m_Quirk(nullptr) + m_Quirk((SmartAttributeParsedData::SmartQuirk) 0) { if (disk) m_Quirk = getQuirk(disk->model(), disk->firmware()); @@ -63,7 +64,6 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, QString worst = QString::fromLocal8Bit("worst"); QString thresh = QString::fromLocal8Bit("thresh"); QString raw = QString::fromLocal8Bit("raw"); - QString str = QString::fromLocal8Bit("string"); QString flags = QString::fromLocal8Bit("flags"); QString prefailure = QString::fromLocal8Bit("prefailure"); QString online = QString::fromLocal8Bit("updated_online"); @@ -75,7 +75,7 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, QJsonObject rawObj = jsonAttribute[raw].toObject(); - m_Raw = rawObj[str].toString().toULongLong(); + m_Raw = rawObj[value].toVariant().toULongLong(); QJsonObject flagsObj = jsonAttribute[flags].toObject(); @@ -264,119 +264,119 @@ bool SmartAttributeParsedData::updateUnit() if (m_Quirk) { switch (id()) { case 3: - if (*m_Quirk & SMART_QUIRK_3_UNUSED) { + if (m_Quirk & SMART_QUIRK_3_UNUSED) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; return true; } break; case 4: - if (*m_Quirk & SMART_QUIRK_4_UNUSED) { + if (m_Quirk & SMART_QUIRK_4_UNUSED) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; return true; } break; case 5: - if (*m_Quirk & SMART_QUIRK_5_UNKNOWN) + if (m_Quirk & SMART_QUIRK_5_UNKNOWN) return false; break; case 9: - if (*m_Quirk & SMART_QUIRK_9_POWERONMINUTES) { + if (m_Quirk & SMART_QUIRK_9_POWERONMINUTES) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; return true; - } else if (*m_Quirk & SMART_QUIRK_9_POWERONSECONDS) { + } else if (m_Quirk & SMART_QUIRK_9_POWERONSECONDS) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; return true; - } else if (*m_Quirk & SMART_QUIRK_9_POWERONHALFMINUTES) { + } else if (m_Quirk & SMART_QUIRK_9_POWERONHALFMINUTES) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; return true; - } else if (*m_Quirk & SMART_QUIRK_9_UNKNOWN) + } else if (m_Quirk & SMART_QUIRK_9_UNKNOWN) return false; break; case 190: - if (*m_Quirk & SMART_QUIRK_190_UNKNOWN) + if (m_Quirk & SMART_QUIRK_190_UNKNOWN) return false; break; case 192: - if (*m_Quirk & SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) { + if (m_Quirk & SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; return true; } break; case 194: - if (*m_Quirk & SMART_QUIRK_194_10XCELSIUS) { + if (m_Quirk & SMART_QUIRK_194_10XCELSIUS) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MKELVIN; return true; - } else if (*m_Quirk & SMART_QUIRK_194_UNKNOWN) + } else if (m_Quirk & SMART_QUIRK_194_UNKNOWN) return false; break; case 197: - if (*m_Quirk & SMART_QUIRK_197_UNKNOWN) + if (m_Quirk & SMART_QUIRK_197_UNKNOWN) return false; break; case 198: - if (*m_Quirk & SMART_QUIRK_198_UNKNOWN) + if (m_Quirk & SMART_QUIRK_198_UNKNOWN) return false; break; case 200: - if (*m_Quirk & SMART_QUIRK_200_WRITEERRORCOUNT) { + if (m_Quirk & SMART_QUIRK_200_WRITEERRORCOUNT) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; return true; } break; case 201: - if (*m_Quirk & SMART_QUIRK_201_DETECTEDTACOUNT) { + if (m_Quirk & SMART_QUIRK_201_DETECTEDTACOUNT) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; return true; } break; case 225: - if (*m_Quirk & SMART_QUIRK_225_TOTALLBASWRITTEN) { + if (m_Quirk & SMART_QUIRK_225_TOTALLBASWRITTEN) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MB; return true; } break; case 226: - if (*m_Quirk & SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) { + if (m_Quirk & SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; return true; } break; case 227: - if (*m_Quirk & SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) { + if (m_Quirk & SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; return true; } break; case 228: - if (*m_Quirk & SMART_QUIRK_228_WORKLOADTIMER) { + if (m_Quirk & SMART_QUIRK_228_WORKLOADTIMER) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; return true; } break; case 232: - if (*m_Quirk & SMART_QUIRK_232_AVAILABLERESERVEDSPACE) { + if (m_Quirk & SMART_QUIRK_232_AVAILABLERESERVEDSPACE) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; return true; } break; case 233: - if (*m_Quirk & SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) { + if (m_Quirk & SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) { m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; return true; } @@ -628,7 +628,7 @@ static const SmartAttributeParsedData::SmartQuirkDataBase *quirkDatabase() return quirkDb; } -static SmartAttributeParsedData::SmartQuirk *getQuirk(QString model, QString firmware) +static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware) { const SmartAttributeParsedData::SmartQuirkDataBase *db; @@ -646,8 +646,8 @@ static SmartAttributeParsedData::SmartQuirk *getQuirk(QString model, QString fir if (!firmwareRegex.exactMatch(firmware)) continue; } - return (SmartAttributeParsedData::SmartQuirk *)&db->quirk; + return db->quirk; } - return nullptr; + return (SmartAttributeParsedData::SmartQuirk) 0; } diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index 641b5ea..2868fb7 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -201,7 +201,7 @@ private: bool m_Warn; SmartAttributeUnit m_PrettyUnit; SmartDiskInformation *m_Disk; - SmartQuirk *m_Quirk; + SmartQuirk m_Quirk; }; #endif // SMARTATTRIBUTEPARSEDDATA_H diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index cf701ef..b220279 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -154,7 +154,7 @@ bool SmartDiskInformation::updatePowerCycle() void SmartDiskInformation::validateBadAttributes() { - foreach (SmartAttributeParsedData attribute, m_Attributes) { + for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) { if (attribute.prefailure()) { if (attribute.goodNowValid() && !attribute.goodNow()) m_BadAttributeNow = true; @@ -167,7 +167,7 @@ void SmartDiskInformation::validateBadAttributes() SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id) { SmartAttributeParsedData *attr = nullptr; - foreach (SmartAttributeParsedData attribute, m_Attributes) { + for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) { if (id == attribute.id()) { attr = new SmartAttributeParsedData(attribute); break; diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index 81a8214..51b9350 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -20,11 +20,12 @@ #include "core/smartattributeparseddata.h" #include "core/smartdiskinformation.h" +#include "util/externalcommand.h" + #include #include #include #include -#include #include SmartParser::SmartParser(const QString &device_path) : @@ -80,7 +81,7 @@ bool SmartParser::init() m_DiskInformation->setModel(smartJson[model_name].toString()); m_DiskInformation->setFirmware(smartJson[firmware].toString()); m_DiskInformation->setSerial(smartJson[serial_number].toString()); - m_DiskInformation->setSize(smartJson[user_capacity].toString().toULongLong()); + m_DiskInformation->setSize(smartJson[user_capacity].toVariant().toULongLong()); QJsonObject selfTest = smartJson[self_test].toObject(); QJsonObject selfTestStatus = selfTest[status].toObject(); @@ -114,20 +115,15 @@ void SmartParser::loadSmartOutput() args.append(QString::fromLocal8Bit("-j")); args.append(devicePath()); - QProcess smartctl; - smartctl.start(QString::fromLocal8Bit("smartctl"), args); + ExternalCommand smartctl(QString::fromLocal8Bit("smartctl"), args); - bool success = smartctl.waitForFinished(); + if (smartctl.run() && smartctl.exitCode() == 0) { + QByteArray output = smartctl.rawOutput(); - if (!success || smartctl.exitStatus() == QProcess::CrashExit) { - qDebug() << "smartctl initialization failed for " << devicePath() << ": " << strerror(errno); - return; + m_SmartOutput = QJsonDocument::fromJson(output); } - - QByteArray output = smartctl.readAllStandardOutput(); - smartctl.close(); - - m_SmartOutput = QJsonDocument::fromJson(output); + else + qDebug() << "smartctl initialization failed for " << devicePath() << ": " << strerror(errno); } } @@ -152,7 +148,7 @@ void SmartParser::loadAttributes() return; } - foreach (QJsonValue value, attributeArray) { + for (const QJsonValue &value : qAsConst(attributeArray)) { SmartAttributeParsedData parsedObject(m_DiskInformation, value.toObject()); m_DiskInformation->addAttribute(parsedObject); } diff --git a/src/core/smartstatus.cpp b/src/core/smartstatus.cpp index 60c8d6e..3c8a35a 100644 --- a/src/core/smartstatus.cpp +++ b/src/core/smartstatus.cpp @@ -230,7 +230,7 @@ void SmartStatus::addAttributes(QList attr) { m_Attributes.clear(); - foreach (SmartAttributeParsedData at, attr) { + for (const SmartAttributeParsedData &at : qAsConst(attr)) { SmartAttribute sm(at); m_Attributes.append(sm); } From 44fae61d4f128adf08d524480efc38513cfa9c3e Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 9 Jan 2018 19:34:20 -0300 Subject: [PATCH 011/175] - Removing libatasmart dependency from CMakeLists.txt - Changing getQuirk regular expression evaluation to use QRegularExpression instead of QRegExp --- CMakeLists.txt | 1 - src/core/smartattributeparseddata.cpp | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f863a7..4d58521 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,6 @@ kde_enable_exceptions() find_package(PkgConfig REQUIRED) pkg_check_modules(BLKID REQUIRED blkid>=2.30) -pkg_check_modules(LIBATASMART REQUIRED libatasmart) include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index 3b21ccd..f793338 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL)) @@ -632,18 +632,20 @@ static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firm { const SmartAttributeParsedData::SmartQuirkDataBase *db; - QRegExp modelRegex; - QRegExp firmwareRegex; + QRegularExpression modelRegex; + QRegularExpression firmwareRegex; for (db = quirkDatabase(); db->model || db->firmware; db++) { if (db->model) { modelRegex.setPattern(QString::fromLocal8Bit(db->model)); - if (!modelRegex.exactMatch(model)) + QRegularExpressionMatch match = modelRegex.match(model); + if (!match.hasMatch()) continue; } if (db->firmware) { firmwareRegex.setPattern(QString::fromLocal8Bit(db->firmware)); - if (!firmwareRegex.exactMatch(firmware)) + QRegularExpressionMatch match = firmwareRegex.match(firmware); + if (!match.hasMatch()) continue; } return db->quirk; From 4069e5112e944bb83fad483c26837f0e87c0cb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 11 Jan 2018 11:39:15 +0100 Subject: [PATCH 012/175] Post merge fixes. In kauth branch ExternalCommand::write should be called before start. --- src/fs/luks.cpp | 2 +- src/fs/luks2.cpp | 11 +++++------ src/fs/udf.cpp | 5 ++--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index b80bb39..1554523 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -690,7 +690,7 @@ void luks::setPayloadSize() bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode }); - if (cmd.start(-1) && cmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 && cmd.waitFor() && cmd.exitCode() == 0) + if (cmd.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.waitFor() && cmd.exitCode() == 0) return true; return false; diff --git a/src/fs/luks2.cpp b/src/fs/luks2.cpp index 72e5554..9453ee1 100644 --- a/src/fs/luks2.cpp +++ b/src/fs/luks2.cpp @@ -56,9 +56,8 @@ bool luks2::create(Report& report, const QString& deviceNode) QStringLiteral("--type"), QStringLiteral("luks2"), QStringLiteral("luksFormat"), deviceNode }); - if (!( createCmd.start(-1) && - createCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && - createCmd.waitFor() && createCmd.exitCode() == 0)) + if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && + createCmd.start(-1) && createCmd.waitFor() && createCmd.exitCode() == 0)) { return false; } @@ -68,7 +67,7 @@ bool luks2::create(Report& report, const QString& deviceNode) deviceNode, suggestedMapperName(deviceNode) }); - if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor())) + if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) return false; setPayloadSize(); @@ -95,12 +94,12 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); - cryptResizeCmd.start(-1); if (m_KeyLocation == keyring) { if (m_passphrase.isEmpty()) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); } + cryptResizeCmd.start(-1); cryptResizeCmd.waitFor(); if ( cryptResizeCmd.exitCode() == 0 ) return m_innerFs->resize(report, mapperName(), m_PayloadSize); @@ -111,12 +110,12 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) { QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); - cryptResizeCmd.start(-1); if (m_KeyLocation == keyring) { if (m_passphrase.isEmpty()) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); } + cryptResizeCmd.start(-1); cryptResizeCmd.waitFor(); if ( cryptResizeCmd.exitCode() == 0 ) return true; diff --git a/src/fs/udf.cpp b/src/fs/udf.cpp index 1b0900f..f34c5f3 100644 --- a/src/fs/udf.cpp +++ b/src/fs/udf.cpp @@ -52,9 +52,8 @@ void udf::init() if (m_Create == cmdSupportFileSystem) { // Detect old mkudffs prior to version 1.1 by lack of --label option -// ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") }); -// oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label")); - oldMkudffsVersion = false; + ExternalCommand cmd(QStringLiteral("mkudffs"), { QStringLiteral("--help") }); + oldMkudffsVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("--label")); } } From ed7c5b1c77fda2d8fabad6ae0a36090c78a8eab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 11 Jan 2018 12:00:52 +0100 Subject: [PATCH 013/175] Use long command line option for smartctl. --- src/core/smartparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index 51b9350..f95ed7b 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -112,7 +112,7 @@ void SmartParser::loadSmartOutput() if (m_SmartOutput.isEmpty()) { QStringList args; args.append(QString::fromLocal8Bit("--all")); - args.append(QString::fromLocal8Bit("-j")); + args.append(QString::fromLocal8Bit("--json")); args.append(devicePath()); ExternalCommand smartctl(QString::fromLocal8Bit("smartctl"), args); From a135c86ba11f5e8006eac62d886d49a547ec1a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 11 Jan 2018 14:14:01 +0100 Subject: [PATCH 014/175] Use QStringLiteral instead of QString::fromLocal8Bit --- src/core/smartattributeparseddata.cpp | 16 +++++++------- src/core/smartparser.cpp | 31 +++++++++++---------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index f793338..8c195cd 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -59,14 +59,14 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, m_Quirk = getQuirk(disk->model(), disk->firmware()); if (!jsonAttribute.isEmpty()) { - QString id = QString::fromLocal8Bit("id"); - QString value = QString::fromLocal8Bit("value"); - QString worst = QString::fromLocal8Bit("worst"); - QString thresh = QString::fromLocal8Bit("thresh"); - QString raw = QString::fromLocal8Bit("raw"); - QString flags = QString::fromLocal8Bit("flags"); - QString prefailure = QString::fromLocal8Bit("prefailure"); - QString online = QString::fromLocal8Bit("updated_online"); + QString id = QStringLiteral("id"); + QString value = QStringLiteral("value"); + QString worst = QStringLiteral("worst"); + QString thresh = QStringLiteral("thresh"); + QString raw = QStringLiteral("raw"); + QString flags = QStringLiteral("flags"); + QString prefailure = QStringLiteral("prefailure"); + QString online = QStringLiteral("updated_online"); m_Id = jsonAttribute[id].toInt(); m_CurrentValue = jsonAttribute[value].toInt(); diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index f95ed7b..cfe1f5f 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -44,16 +44,16 @@ bool SmartParser::init() QJsonObject smartJson = m_SmartOutput.object(); - QString model_name = QString::fromLocal8Bit("model_name"); - QString firmware = QString::fromLocal8Bit("firmware_version"); - QString serial_number = QString::fromLocal8Bit("serial_number"); - QString device = QString::fromLocal8Bit("device"); - QString smart_status = QString::fromLocal8Bit("smart_status"); - QString passed = QString::fromLocal8Bit("passed"); - QString self_test = QString::fromLocal8Bit("self_test"); - QString status = QString::fromLocal8Bit("status"); - QString value = QString::fromLocal8Bit("value"); - QString user_capacity = QString::fromLocal8Bit("user_capacity"); + QString model_name = QStringLiteral("model_name"); + QString firmware = QStringLiteral("firmware_version"); + QString serial_number = QStringLiteral("serial_number"); + QString device = QStringLiteral("device"); + QString smart_status = QStringLiteral("smart_status"); + QString passed = QStringLiteral("passed"); + QString self_test = QStringLiteral("self_test"); + QString status = QStringLiteral("status"); + QString value = QStringLiteral("value"); + QString user_capacity = QStringLiteral("user_capacity"); if (!smartJson.contains(device)) { qDebug() << "smart disk open failed for " << devicePath() << ": " << strerror(errno); @@ -110,12 +110,7 @@ bool SmartParser::init() void SmartParser::loadSmartOutput() { if (m_SmartOutput.isEmpty()) { - QStringList args; - args.append(QString::fromLocal8Bit("--all")); - args.append(QString::fromLocal8Bit("--json")); - args.append(devicePath()); - - ExternalCommand smartctl(QString::fromLocal8Bit("smartctl"), args); + ExternalCommand smartctl(QStringLiteral("smartctl"), { QStringLiteral("--all"), QStringLiteral("--json"), devicePath() }); if (smartctl.run() && smartctl.exitCode() == 0) { QByteArray output = smartctl.rawOutput(); @@ -136,8 +131,8 @@ void SmartParser::loadAttributes() QJsonObject smartJson = m_SmartOutput.object(); - QString ata_smart_attributes = QString::fromLocal8Bit("ata_smart_attributes"); - QString table = QString::fromLocal8Bit("table"); + QString ata_smart_attributes = QStringLiteral("ata_smart_attributes"); + QString table = QStringLiteral("table"); QJsonObject ataSmartAttributes = smartJson[ata_smart_attributes].toObject(); From 0190d32cf6961c19a90617de05858a688245a928 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Thu, 11 Jan 2018 17:38:53 -0300 Subject: [PATCH 015/175] Including doxygen comments to the new SMART support classes --- src/core/smartattributeparseddata.cpp | 9 ++++++ src/core/smartattributeparseddata.h | 46 ++++++++++++++++----------- src/core/smartdiskinformation.cpp | 16 ++++++++++ src/core/smartdiskinformation.h | 32 ++++++++++++------- src/core/smartparser.cpp | 6 ++++ src/core/smartparser.h | 10 ++++-- 6 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index 8c195cd..3de8344 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -33,6 +33,10 @@ static const QMap tableUnit(); static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware); +/** Creates a new SmartAttributeParsedData object. + @param disk the reference to the disk that this attribute is allocated to + @param jsonAttribute JSON attribute data +*/ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, QJsonObject jsonAttribute) : m_Id(0), @@ -93,6 +97,8 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, } } +/** @param other SmartAttributeParsedData to copy +*/ SmartAttributeParsedData::SmartAttributeParsedData(const SmartAttributeParsedData &other) : m_Id(other.id()), m_CurrentValue(other.currentValue()), @@ -117,6 +123,7 @@ SmartAttributeParsedData::SmartAttributeParsedData(const SmartAttributeParsedDat } +/** Validate values from the current attribute */ void SmartAttributeParsedData::validateValues() { m_CurrentValueValid = m_CurrentValue >= 1 && m_CurrentValue <= 0xFD; @@ -137,6 +144,7 @@ void SmartAttributeParsedData::validateValues() m_Warn = (m_GoodNowValid && !m_GoodNow) || (m_GoodInThePastValid && !m_GoodInThePast); } +/** Make a pretty value from raw based on attribute's id */ void SmartAttributeParsedData::makePretty() { if (m_PrettyUnit == SMART_ATTRIBUTE_UNIT_UNKNOWN) @@ -206,6 +214,7 @@ void SmartAttributeParsedData::makePretty() } } +/** Verify attribute's unit */ void SmartAttributeParsedData::verifyAttribute() { if (id() == 3 || id() == 226) diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index 2868fb7..d11a6bb 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -23,9 +23,17 @@ class SmartDiskInformation; +/** A SMART parsed attribute. + + It receives the attribute data from JSON, retrieve its data and validates its values. + + @author Caio Carvalho +*/ class SmartAttributeParsedData { public: + + /** A unit for SMART attributes */ enum SmartAttributeUnit { SMART_ATTRIBUTE_UNIT_UNKNOWN, SMART_ATTRIBUTE_UNIT_NONE, @@ -38,6 +46,7 @@ public: _SMART_ATTRIBUTE_UNIT_MAX }; + /** SMART Quirk */ enum SmartQuirk { SMART_QUIRK_9_POWERONMINUTES = 0x000001, SMART_QUIRK_9_POWERONSECONDS = 0x000002, @@ -63,6 +72,7 @@ public: SMART_QUIRK_3_UNUSED = 0x200000 }; + /** SMART Quirk to some particular model and firmware */ struct SmartQuirkDataBase { const char *model; const char *firmware; @@ -77,92 +87,92 @@ public: public: quint32 id() const { - return m_Id; + return m_Id; /**< @return attribute id */ } qint32 currentValue() const { - return m_CurrentValue; + return m_CurrentValue; /**< @return attribute current value */ } qint32 worstValue() const { - return m_WorstValue; + return m_WorstValue; /**< @return attribute worst value */ } qint32 threshold() const { - return m_Threshold; + return m_Threshold; /**< @return attribute threshold value */ } bool prefailure() const { - return m_Prefailure; + return m_Prefailure; /**< @return attribute prefailure status */ } bool online() const { - return m_Online; + return m_Online; /**< @return attribute online status */ } quint64 raw() const { - return m_Raw; + return m_Raw; /**< @return attribute raw value */ } quint64 prettyValue() const { - return m_PrettyValue; + return m_PrettyValue; /**< @return attribute pretty value */ } SmartAttributeUnit prettyUnit() const { - return m_PrettyUnit; + return m_PrettyUnit; /**< @return pretty unit value */ } bool goodNowValid() const { - return m_GoodNowValid; + return m_GoodNowValid; /**< @return good now attribute status validation */ } bool goodNow() const { - return m_GoodNow; + return m_GoodNow; /**< @return good now attribute status */ } bool goodInThePastValid() const { - return m_GoodInThePastValid; + return m_GoodInThePastValid; /**< @return good in the past attribute status validation */ } bool goodInThePast() const { - return m_GoodInThePast; + return m_GoodInThePast; /**< @return good in the past attribute status */ } bool thresholdValid() const { - return m_ThresholdValid; + return m_ThresholdValid; /**< @return threshold value validation */ } bool currentValueValid() const { - return m_CurrentValueValid; + return m_CurrentValueValid; /**< @return current value validation */ } bool worstValueValid() const { - return m_WorstValueValid; + return m_WorstValueValid; /**< @return worst value validation */ } bool warn() const { - return m_Warn; + return m_Warn; /**< @return warn status */ } SmartDiskInformation *disk() const { - return m_Disk; + return m_Disk; /**< @return attribute's disk reference */ } protected: diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index b220279..f227692 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -20,6 +20,7 @@ static quint64 u64log2(quint64 n); +/** Creates a new SmartDiskInformationObject */ SmartDiskInformation::SmartDiskInformation() : m_ModelName(QString()), m_FirmwareVersion(QString()), @@ -38,6 +39,7 @@ SmartDiskInformation::SmartDiskInformation() : } +/** Update the number of bad sectors based on reallocated sector count and current pending sector attributes data */ void SmartDiskInformation::updateBadSectors() { SmartAttributeParsedData *reallocatedSectorCt; @@ -56,6 +58,7 @@ void SmartDiskInformation::updateBadSectors() m_BadSectors = currentPendingSector->prettyValue(); } +/** Update SMART overall data based on the quantity of bad sectors and the status of SMART attributes */ void SmartDiskInformation::updateOverall() { if (!smartStatus()) { @@ -91,6 +94,9 @@ void SmartDiskInformation::updateOverall() } +/** Update the temperature value based on SMART attributes + @return a boolean representing the status of the operation +*/ bool SmartDiskInformation::updateTemperature() { SmartAttributeParsedData *temperatureCelsius; @@ -118,6 +124,9 @@ bool SmartDiskInformation::updateTemperature() return false; } +/** Update the powered on value based on SMART attributes + @return a boolean representing the status of the operation +*/ bool SmartDiskInformation::updatePowerOn() { SmartAttributeParsedData *powerOnHours; @@ -138,6 +147,9 @@ bool SmartDiskInformation::updatePowerOn() return false; } +/** Update the power cycles value based on SMART attributes + @return a boolean representing the status of the operation +*/ bool SmartDiskInformation::updatePowerCycle() { SmartAttributeParsedData *powerCycleCount; @@ -152,6 +164,7 @@ bool SmartDiskInformation::updatePowerCycle() return false; } +/** Validate disk attributes status */ void SmartDiskInformation::validateBadAttributes() { for (const SmartAttributeParsedData &attribute : qAsConst(m_Attributes)) { @@ -164,6 +177,9 @@ void SmartDiskInformation::validateBadAttributes() } } +/** Search for a attribute based on its id number + @return a reference to the attribute +*/ SmartAttributeParsedData *SmartDiskInformation::findAttribute(quint32 id) { SmartAttributeParsedData *attr = nullptr; diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index 9c9ba4f..cc79cf0 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -23,9 +23,16 @@ class SmartAttributeParsedData; +/** Disk information retrieved by SMART. + + It includes a list with your SMART attributes. + + @author Caio Carvalho +*/ class SmartDiskInformation { public: + /** SMART self test execution state */ enum SmartSelfTestExecutionStatus { SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER = 0, SMART_SELF_TEST_EXECUTION_STATUS_ABORTED = 1, @@ -40,6 +47,7 @@ public: _SMART_SELF_TEST_EXECUTION_STATUS_MAX }; + /** SMART overall state */ enum SmartOverall { SMART_OVERALL_GOOD, SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST, @@ -69,62 +77,62 @@ public: public: const QString model() const { - return m_ModelName; + return m_ModelName; /**< @return the disk model name */ } const QString firmware() const { - return m_FirmwareVersion; + return m_FirmwareVersion; /**< @return the disk firmware version */ } const QString serial() const { - return m_SerialNumber; + return m_SerialNumber; /**< @return the disk serial number */ } quint64 size() const { - return m_Size; + return m_Size; /**< @return disk size */ } bool smartStatus() const { - return m_SmartStatus; + return m_SmartStatus; /**< @return a boolean representing SMART status */ } SmartSelfTestExecutionStatus selfTestExecutionStatus() const { - return m_SelfTestExecutionStatus; + return m_SelfTestExecutionStatus; /**< @return SMART self execution status */ } SmartOverall overall() const { - return m_Overall; + return m_Overall; /**< @return SMART overall status */ } quint64 temperature() const { - return m_Temperature; + return m_Temperature; /**< @return disk temperature in kelvin */ } quint64 badSectors() const { - return m_BadSectors; + return m_BadSectors; /**< @return the number of bad sectors */ } quint64 poweredOn() const { - return m_PoweredOn; + return m_PoweredOn; /**< @return quantity of time that device is powered on */ } quint64 powerCycles() const { - return m_PowerCycles; + return m_PowerCycles; /**< @return quantity of power cycles */ } QList attributes() const { - return m_Attributes; + return m_Attributes; /**< @return a list that contains the disk SMART attributes */ } public: diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index cfe1f5f..5e4716a 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -28,6 +28,9 @@ #include #include +/** Creates a new SmartParser object + @param device_path device path that indicates the device that SMART must analyse +*/ SmartParser::SmartParser(const QString &device_path) : m_DevicePath(device_path), m_DiskInformation(nullptr) @@ -35,6 +38,7 @@ SmartParser::SmartParser(const QString &device_path) : } +/** Initialize SmartParser data, retrieve the information from SMART JSON and initialize the disk information data */ bool SmartParser::init() { loadSmartOutput(); @@ -107,6 +111,7 @@ bool SmartParser::init() return true; } +/** Run smartctl command and recover its output */ void SmartParser::loadSmartOutput() { if (m_SmartOutput.isEmpty()) { @@ -122,6 +127,7 @@ void SmartParser::loadSmartOutput() } } +/** Load SMART disk attributes from JSON data */ void SmartParser::loadAttributes() { loadSmartOutput(); diff --git a/src/core/smartparser.h b/src/core/smartparser.h index 7a199fa..6160492 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -23,6 +23,12 @@ class SmartDiskInformation; +/** A parser to SMART JSON output. + + Responsable to execute smartctl and parse its output. + + @author Caio Carvalho +*/ class SmartParser { public: @@ -34,12 +40,12 @@ public: public: const QString &devicePath() const { - return m_DevicePath; + return m_DevicePath; /**< @return the device path that SMART must analyse */ } SmartDiskInformation *diskInformation() const { - return m_DiskInformation; + return m_DiskInformation; /**< @return a reference to parsed disk information */ } protected: From 1c024c6b2909cd6c8d0a0ded96d651cfba7b3437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 11 Jan 2018 21:59:18 +0100 Subject: [PATCH 016/175] Fix a typo in the comment. --- src/core/smartparser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/smartparser.h b/src/core/smartparser.h index 6160492..3438e8d 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -25,7 +25,7 @@ class SmartDiskInformation; /** A parser to SMART JSON output. - Responsable to execute smartctl and parse its output. + Responsible to execute smartctl and parse its output. @author Caio Carvalho */ From d2ee0010d0dcb4dbcedccb9aacec5cd40204a521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 12 Jan 2018 11:32:09 +0100 Subject: [PATCH 017/175] Update credits. --- src/util/helpers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/helpers.cpp b/src/util/helpers.cpp index 87661e0..6f1e3fb 100644 --- a/src/util/helpers.cpp +++ b/src/util/helpers.cpp @@ -67,6 +67,7 @@ KAboutData aboutKPMcore() aboutData.addCredit(xi18nc("@info:credit", "Chantara Tith"), i18nc("@info:credit", "LVM support"), QStringLiteral("tith.chantara@gmail.com")); aboutData.addCredit(xi18nc("@info:credit", "Pali Rohár"), i18nc("@info:credit", "UDF support"), QStringLiteral("pali.rohar@gmail.com")); aboutData.addCredit(xi18nc("@info:credit", "Adriaan de Groot"), i18nc("@info:credit", "Calamares maintainer"), QStringLiteral("groot@kde.org")); + aboutData.addCredit(xi18nc("@info:credit", "Caio Carvalho"), i18nc("@info:credit", "Improved SMART support"), QStringLiteral("caiojcarvalho@gmail.com")); return aboutData; } From b5303587e2861e18f87e52f5aa76ebdcd7ae4af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 16 Jan 2018 15:31:38 +0100 Subject: [PATCH 018/175] Update INSTALL instructions. * bzip2->xz. * Remove libatasmart. --- INSTALL | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/INSTALL b/INSTALL index 7abd18e..a2f232e 100644 --- a/INSTALL +++ b/INSTALL @@ -4,24 +4,16 @@ Building and installing KDE Partition Manager Core Library from source 1. Dependencies -libparted: Either get it from http://www.gnu.org/software/parted/download.shtml -and build it yourself or, preferably, install your distribution's packages -(don't forget the dev-package). - -libblkid: Part of the util-linux project available at -https://github.com/karelzak/util-linux - -libatasmart: Available from http://0pointer.de/blog/projects/being-smart.html +util-linux 2.32: available at https://github.com/karelzak/util-linux KDE Frameworks: The minimum required version is 5.0. - 2. Configure KPMcore is built with cmake. It is recommended to build out of tree: After unpacking the source, create a separate build directory and run cmake there: -$ tar xfj kpmcore-x.y.z.tar.bz2 +$ tar xf kpmcore-x.y.z.tar.xz $ cd kpmcore-x.y.z $ mkdir build $ cd build From 49c0c39f4b889c9d7af5adf33805d5834950306c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sat, 20 Jan 2018 21:56:10 -0300 Subject: [PATCH 019/175] - Including SMART support test - Adding export macro to SmartParser --- src/core/smartparser.h | 4 +- test/CMakeLists.txt | 4 ++ test/testsmart.cpp | 102 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/testsmart.cpp diff --git a/src/core/smartparser.h b/src/core/smartparser.h index 3438e8d..ace6135 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -18,6 +18,8 @@ #if !defined(KPMCORE_SMARTPARSER_H) #define KPMCORE_SMARTPARSER_H +#include "util/libpartitionmanagerexport.h" + #include #include @@ -29,7 +31,7 @@ class SmartDiskInformation; @author Caio Carvalho */ -class SmartParser +class LIBKPMCORE_EXPORT SmartParser { public: SmartParser(const QString &device_path); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e81581e..67b9cea 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,3 +52,7 @@ find_package (Threads) # Execute external commands as root kpm_test(testexternalcommand testexternalcommand.cpp) add_test(NAME testexternalcommand COMMAND testexternalcommand ${BACKEND}) + +# Test SMART support +kpm_test(testsmart testsmart.cpp) +add_test(NAME testsmart COMMAND testsmart ${BACKEND}) diff --git a/test/testsmart.cpp b/test/testsmart.cpp new file mode 100644 index 0000000..ea5aa72 --- /dev/null +++ b/test/testsmart.cpp @@ -0,0 +1,102 @@ +#include "helpers.h" + +#include "util/externalcommand.h" +#include "backend/corebackend.h" +#include "backend/corebackendmanager.h" +#include "core/smartstatus.h" +#include "core/smartparser.h" + +#include +#include + +static QString getDefaultDevicePath(); +static bool testSmartStatus(); +static bool testSmartParser(); + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + KPMCoreInitializer i; + + if (argc == 2) + i = KPMCoreInitializer(argv[1]); + + if (!i.isValid()) + return 1; + + CoreBackend *backend = CoreBackendManager::self()->backend(); + + if (!backend) + { + qWarning() << "Couldn't get backend."; + return 1; + } + + if (!testSmartStatus() || !testSmartParser()) + return 1; + + return app.exec(); +} + +static QString getDefaultDevicePath() +{ + // Getting default home partition using 'df -P /home | awk 'END{print $1}'' command + ExternalCommand command(QStringLiteral("df"), { QStringLiteral("-P"), QStringLiteral("/home"), QStringLiteral("|"), + QStringLiteral("awk"), QStringLiteral("\'END{print $1}\'") }); + + if (command.run() && command.exitCode() == 0) { + QString output = command.output(); + return output; + } + + return QString(); +} + +static bool testSmartStatus() +{ + QString devicePath = getDefaultDevicePath(); + + SmartStatus smart(devicePath); + + if (smart.devicePath() != devicePath) + return false; + + if (!smart.status()) + return false; + + if (smart.modelName() == QString()) + return false; + + if (smart.firmware() == QString()) + return false; + + if (smart.serial() == QString()) + return false; + + if (smart.selfTestStatus()) + return false; + + if (!smart.isValid()) + return false; + + return true; +} + +static bool testSmartParser() +{ + QString devicePath = getDefaultDevicePath(); + + SmartParser parser(devicePath); + + if (!parser.init()) + return false; + + if (parser.devicePath() != devicePath) + return false; + + if (!parser.diskInformation()) + return false; + + return true; +} From a3d43e159fb5cb519510070a90dd333d1ab0cf6b Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 21 Jan 2018 01:41:59 -0300 Subject: [PATCH 020/175] Removing LIBKPMCORE_EXPORT from SmartParser and adding SMART support dependencies to testsmart in cmake --- src/core/smartparser.h | 4 +--- test/CMakeLists.txt | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/smartparser.h b/src/core/smartparser.h index ace6135..3438e8d 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -18,8 +18,6 @@ #if !defined(KPMCORE_SMARTPARSER_H) #define KPMCORE_SMARTPARSER_H -#include "util/libpartitionmanagerexport.h" - #include #include @@ -31,7 +29,7 @@ class SmartDiskInformation; @author Caio Carvalho */ -class LIBKPMCORE_EXPORT SmartParser +class SmartParser { public: SmartParser(const QString &device_path); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 67b9cea..66681e1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,6 +53,11 @@ find_package (Threads) kpm_test(testexternalcommand testexternalcommand.cpp) add_test(NAME testexternalcommand COMMAND testexternalcommand ${BACKEND}) +# Including SMART files reference +set(SMARTPARSER ${CMAKE_SOURCE_DIR}/src/core/smartdiskinformation.cpp + ${CMAKE_SOURCE_DIR}/src/core/smartattributeparseddata.cpp + ${CMAKE_SOURCE_DIR}/src/core/smartparser.cpp) + # Test SMART support -kpm_test(testsmart testsmart.cpp) +kpm_test(testsmart testsmart.cpp ${SMARTPARSER}) add_test(NAME testsmart COMMAND testsmart ${BACKEND}) From e42a5c928964a79d11c46167cd73652bb50cece9 Mon Sep 17 00:00:00 2001 From: Huzaifa Faruqui Date: Wed, 24 Jan 2018 15:22:42 +0000 Subject: [PATCH 021/175] Implement copyblocks function in KAuth helper. Switch BackupFileSystemJob to thenew copyblocks function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed and cleaned up by: Andrius Štikonas --- src/core/copysource.h | 2 + src/core/copysourcedevice.cpp | 5 + src/core/copysourcedevice.h | 6 +- src/core/copysourcefile.h | 3 + src/core/copysourceshred.h | 4 + src/core/copytarget.h | 3 +- src/core/copytargetdevice.cpp | 6 +- src/core/copytargetdevice.h | 1 + src/core/copytargetfile.h | 4 + src/jobs/backupfilesystemjob.cpp | 9 +- src/jobs/backupfilesystemjob.h | 2 +- src/util/externalcommand.cpp | 93 +++++++++++++ src/util/externalcommand.h | 13 ++ src/util/externalcommandhelper.cpp | 128 ++++++++++++++++++ src/util/externalcommandhelper.h | 12 ++ .../org.kde.kpmcore.externalcommand.actions | 6 + 16 files changed, 289 insertions(+), 8 deletions(-) diff --git a/src/core/copysource.h b/src/core/copysource.h index d1d9ae6..3f25e7f 100644 --- a/src/core/copysource.h +++ b/src/core/copysource.h @@ -22,6 +22,7 @@ #include class CopyTarget; +class QString; /** Base class for something to copy from. @@ -41,6 +42,7 @@ protected: public: virtual bool open() = 0; + virtual QString path() const = 0; virtual bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) = 0; virtual qint64 length() const = 0; virtual bool overlaps(const CopyTarget& target) const = 0; diff --git a/src/core/copysourcedevice.cpp b/src/core/copysourcedevice.cpp index a0b9d1b..3b91744 100644 --- a/src/core/copysourcedevice.cpp +++ b/src/core/copysourcedevice.cpp @@ -103,3 +103,8 @@ bool CopySourceDevice::overlaps(const CopyTarget& target) const return false; } + +QString CopySourceDevice::path() const +{ + return m_Device.deviceNode(); +} diff --git a/src/core/copysourcedevice.h b/src/core/copysourcedevice.h index 23f060f..04f1734 100644 --- a/src/core/copysourcedevice.h +++ b/src/core/copysourcedevice.h @@ -27,6 +27,7 @@ class Device; class CopyTarget; class CoreBackendDevice; +class QString; /** A Device to copy from. @@ -62,12 +63,13 @@ public: return m_Device; /**< @return Device to copy from */ } + QString path() const override; + protected: Device& m_Device; const qint64 m_FirstByte; const qint64 m_LastByte; - CoreBackendDevice* m_BackendDevice - ; + CoreBackendDevice* m_BackendDevice; }; #endif diff --git a/src/core/copysourcefile.h b/src/core/copysourcefile.h index bad5894..0ff8ff7 100644 --- a/src/core/copysourcefile.h +++ b/src/core/copysourcefile.h @@ -52,6 +52,9 @@ public: qint64 lastByte() const override { return length(); /**< @return equal to length for file. @see length() */ } + QString path() const override { + return m_File.fileName(); + } protected: QFile& file() { diff --git a/src/core/copysourceshred.h b/src/core/copysourceshred.h index df83366..e293531 100644 --- a/src/core/copysourceshred.h +++ b/src/core/copysourceshred.h @@ -24,6 +24,7 @@ #include class CopyTarget; +class QString; /** A source for securely overwriting a partition (shredding). @@ -50,6 +51,9 @@ public: qint64 lastByte() const override { return length(); /**< @return equal to length for shred source. @see length() */ } + QString path() const override { + return m_SourceFile.fileName(); + } protected: QFile& sourceFile() { diff --git a/src/core/copytarget.h b/src/core/copytarget.h index e68d715..97385a1 100644 --- a/src/core/copytarget.h +++ b/src/core/copytarget.h @@ -21,6 +21,7 @@ #include +class QString; /** Base class for something to copy to. @@ -43,7 +44,7 @@ public: virtual bool writeData(QByteArray& buffer, qint64 writeOffset) = 0; virtual qint64 firstByte() const = 0; virtual qint64 lastByte() const = 0; - + virtual QString path() const = 0; qint64 bytesWritten() const { return m_BytesWritten; } diff --git a/src/core/copytargetdevice.cpp b/src/core/copytargetdevice.cpp index e80876c..92e67f2 100644 --- a/src/core/copytargetdevice.cpp +++ b/src/core/copytargetdevice.cpp @@ -23,7 +23,6 @@ #include "core/device.h" - /** Constructs a device to copy to. @param d the Device to copy to @param firstbyte the first byte on the Device to write to @@ -71,3 +70,8 @@ bool CopyTargetDevice::writeData(QByteArray& buffer, qint64 writeOffset) return rval; } + +QString CopyTargetDevice::path() const +{ + return m_Device.deviceNode(); +} diff --git a/src/core/copytargetdevice.h b/src/core/copytargetdevice.h index 062acf7..556b75e 100644 --- a/src/core/copytargetdevice.h +++ b/src/core/copytargetdevice.h @@ -60,6 +60,7 @@ public: const Device& device() const { return m_Device; /**< @return the Device to write to */ } + QString path() const override; protected: Device& m_Device; diff --git a/src/core/copytargetfile.h b/src/core/copytargetfile.h index 3e3ef3e..17ecff2 100644 --- a/src/core/copytargetfile.h +++ b/src/core/copytargetfile.h @@ -49,6 +49,10 @@ public: return bytesWritten(); /**< @return the number of bytes written so far */ } + QString path() const override { + return m_File.fileName(); + } + protected: QFile& file() { return m_File; diff --git a/src/jobs/backupfilesystemjob.cpp b/src/jobs/backupfilesystemjob.cpp index bf72e2f..b1995f3 100644 --- a/src/jobs/backupfilesystemjob.cpp +++ b/src/jobs/backupfilesystemjob.cpp @@ -24,7 +24,7 @@ #include "core/copytargetfile.h" #include "fs/filesystem.h" - +#include "util/externalcommand.h" #include "util/report.h" #include @@ -63,8 +63,11 @@ bool BackupFileSystemJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not open file system on source partition %1 for backup.", sourcePartition().deviceNode()); else if (!copyTarget.open()) report->line() << xi18nc("@info:progress", "Could not create backup file %1.", fileName()); - else - rval = copyBlocks(*report, copyTarget, copySource); + else { + ExternalCommand copyCmd(copySource, copyTarget, QProcess::SeparateChannels); + connect(©Cmd, &ExternalCommand::progress, this, [=] (int percent) { emit progress(percent); }, Qt::QueuedConnection); + rval = copyCmd.startCopyBlocks(-1); + } } jobFinished(*report, rval); diff --git a/src/jobs/backupfilesystemjob.h b/src/jobs/backupfilesystemjob.h index 67a9c92..89f4fb6 100644 --- a/src/jobs/backupfilesystemjob.h +++ b/src/jobs/backupfilesystemjob.h @@ -22,7 +22,7 @@ #include "jobs/job.h" #include - +#include class Partition; class Device; class Report; diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 6ad4971..75e7e3e 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -17,6 +17,11 @@ *************************************************************************/ #include "backend/corebackendmanager.h" +#include "core/device.h" +#include "core/copysource.h" +#include "core/copytarget.h" +#include "core/copysourcedevice.h" +#include "core/copytargetdevice.h" #include "util/externalcommand.h" #include "util/report.h" @@ -32,6 +37,92 @@ #include #include + +ExternalCommand::ExternalCommand(CopySource& source, CopyTarget& target,const QProcess::ProcessChannelMode processChannelMode) : + m_Source(&source), + m_Target(&target), + m_ExitCode(-1) +{ + setup(processChannelMode); +} + + +/** Starts copyBlocks command. + @param timeout timeout to wait for the process to start + @return true on success +*/ +bool ExternalCommand::startCopyBlocks(int timeout) +{ + this->moveToThread(CoreBackendManager::self()->kauthThread()); + QTimer::singleShot(0, this, &ExternalCommand::copyBlocks); + QEventLoop loop; + connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); + loop.exec(); + return true; +} + +bool ExternalCommand::copyBlocks() +{ + bool rval = true; + qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy + qint64 blocksToCopy = m_Source->length() / blockSize; + + qint64 readOffset = m_Source->firstByte(); + qint64 writeOffset = m_Target->firstByte(); + qint32 copyDirection = 1; + + if (m_Target->firstByte() > m_Source->firstByte()) { + readOffset = m_Source->firstByte() + m_Source->length() - blockSize; + writeOffset = m_Target->firstByte() + m_Source->length() - blockSize; + copyDirection = -1; + } + qint64 lastBlock = m_Source->length() % blockSize; + + //report()->line() << xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy, m_source.length(), readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left") : i18nc("direction: right", "right")); + + QString cmd = QStandardPaths::findExecutable(QStringLiteral("dd")); + + if (cmd.isEmpty()) + cmd = QStandardPaths::findExecutable(QStringLiteral("dd"), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); + + qDebug() << "ExternalCommand::copyBlocks\n"; + + KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.copyblockshelper")); + action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); + + arguments.insert(QStringLiteral("command"), cmd); + arguments.insert(QStringLiteral("sourceDevice"), m_Source->path() ); + arguments.insert(QStringLiteral("targetDevice"), m_Target->path()); + arguments.insert(QStringLiteral("blockSize"), blockSize); + arguments.insert(QStringLiteral("blocksToCopy"), blocksToCopy); + arguments.insert(QStringLiteral("readOffset"), readOffset); + arguments.insert(QStringLiteral("writeOffset"), writeOffset); + arguments.insert(QStringLiteral("copyDirection"), copyDirection); + arguments.insert(QStringLiteral("sourceFirstByte"), m_Source->firstByte()); + arguments.insert(QStringLiteral("targetFirstByte"), m_Target->firstByte()); + arguments.insert(QStringLiteral("lastBlock"), lastBlock); + + action.setArguments(arguments); + action.setTimeout(24 * 3600 * 1000); // set 1 day DBus timeout + + KAuth::ExecuteJob *job = action.execute(); + // TODO KF6:Use new signal-slot syntax + connect(job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); + if (!job->exec()) { + qWarning() << "KAuth returned an error code: " << job->errorString(); +// return false; + emit finished(); + return false; + } + + m_Output = job->data()[QStringLiteral("output")].toByteArray(); + setExitCode(job->data()[QStringLiteral("exitCode")].toInt()); + + qDebug() << "ExternalCommand::copyBlocks finished"; + emit finished(); + return true; +} + /** Creates a new ExternalCommand instance without Report. @param cmd the command to run @param args the arguments to pass to the command @@ -74,6 +165,7 @@ void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMod @param timeout timeout to wait for the process to start @return true on success */ + bool ExternalCommand::start(int timeout) { this->moveToThread(CoreBackendManager::self()->kauthThread()); @@ -149,6 +241,7 @@ bool ExternalCommand::waitFor(int timeout) }*/ // onReadOutput(); + return true; } diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index ee9cea4..811b6f8 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -20,6 +20,10 @@ #define KPMCORE_EXTERNALCOMMAND_H #include "util/libpartitionmanagerexport.h" +#include "core/copysourcedevice.h" +#include "core/copytargetfile.h" + +#include #include #include @@ -45,8 +49,10 @@ class LIBKPMCORE_EXPORT ExternalCommand : public QObject public: explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); + explicit ExternalCommand(CopySource& source, CopyTarget& target, QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); public: + bool copyBlocks(); void setCommand(const QString& cmd) { m_Command = cmd; } /**< @param cmd the command to run */ const QString& command() const { return m_Command; } /**< @return the command to run */ @@ -55,6 +61,7 @@ public: void setArgs(const QStringList& args) { m_Args = args; } /**< @param args the new arguments */ bool write(const QByteArray& input); /**< @param input the input for the program */ + bool startCopyBlocks(int timeout =30000); bool start(int timeout = 30000); bool waitFor(int timeout = 30000); bool run(int timeout = 30000); @@ -76,8 +83,12 @@ public: } Q_SIGNALS: + void progress(int); void finished(); +public Q_SLOTS: + void emitProgress(KJob*, unsigned long percent) { emit progress(percent); }; + protected: void execute(); @@ -98,6 +109,8 @@ private: int m_ExitCode; QByteArray m_Output; QByteArray m_Input; + CopySource *m_Source; + CopyTarget *m_Target; }; #endif diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 30a719b..1735f0f 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -18,6 +18,134 @@ #include "externalcommandhelper.h" #include +#include + +bool ExternalCommandHelper::readData(QByteArray& buffer, qint64 offset, qint64 size) +{ + QStringList arguments = { + QStringLiteral("skip=") + QString::number(offset), + QStringLiteral("bs=") + QString::number(size), + QStringLiteral("count=1"), + QStringLiteral("iflag=skip_bytes"), + QStringLiteral("if=") + sourceDevice + }; + + cmd.start(command, arguments); + cmd.waitForFinished(-1); + + if (cmd.exitCode() == 0) { + buffer = cmd.readAllStandardOutput(); + return true; + } + qDebug() << sourceDevice << " " << offset << " " << size << " cmd exitCode " << cmd.exitCode() << "\n"; + return false; +} + +bool ExternalCommandHelper::writeData(QByteArray& buffer, qint64 offset) +{ + QStringList arguments = { + QStringLiteral("of=") + targetDevice, + QStringLiteral("seek=") + QString::number(offset), + QStringLiteral("bs=1M"), + QStringLiteral("oflag=seek_bytes"), + QStringLiteral("conv=fsync") }; + + cmd.start(command, arguments); + cmd.write(buffer); + cmd.closeWriteChannel(); + cmd.waitForFinished(-1); + + if (cmd.exitCode() == 0 ) { + return true; + } + + qDebug() << "cmd exitCode "< 1000) { + // const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); + // const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; + // report.line() << xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); + //} + HelperSupport::progressStep(percent); + } + } + + //const qint64 lastBlock = args[QStringLiteral("lastBlock")]; + + // copy the remainder + if (rval && lastBlock > 0) { + Q_ASSERT(lastBlock < blockSize); + + const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte; + const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte; + //report.line() << xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); + + rval = readData(buffer, lastBlockReadOffset, lastBlock); + + if (rval) + rval = writeData(buffer, lastBlockWriteOffset); + + if (rval){ + qDebug() << "Percent 100"<<"\n"; + emit progress(100); + } + + } + + //report.line() << xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", target.bytesWritten())); + + return reply; +} ActionReply ExternalCommandHelper::start(const QVariantMap& args) { diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 371a3d9..5d2d28d 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -21,6 +21,7 @@ #include +#include #include using namespace KAuth; @@ -29,12 +30,23 @@ class ExternalCommandHelper : public QObject { Q_OBJECT +Q_SIGNALS: + void progress(int); + +public: + bool readData(QByteArray& buffer, qint64 offset, qint64 size); + bool writeData(QByteArray& buffer, qint64 offset); + public Q_SLOTS: ActionReply start(const QVariantMap& args); + ActionReply copyblockshelper(const QVariantMap& args); private: void onReadOutput(); + QString command; + QString sourceDevice; + QString targetDevice; QProcess cmd; // QByteArray output; }; diff --git a/src/util/org.kde.kpmcore.externalcommand.actions b/src/util/org.kde.kpmcore.externalcommand.actions index 0a00710..4d935b2 100644 --- a/src/util/org.kde.kpmcore.externalcommand.actions +++ b/src/util/org.kde.kpmcore.externalcommand.actions @@ -3,3 +3,9 @@ Name=Run external command action Description=Run external command as privileged user Policy=auth_admin Persistence=session + +[org.kde.kpmcore.externalcommand.copyblockshelper] +Name=copy blocks external command action +Description=copy blocks external command as privileged user +Policy=auth_admin +Persistence=session From 61fed73a5d70a1b5438c5e1d2a969e983ad8ce82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 24 Jan 2018 15:35:11 +0000 Subject: [PATCH 022/175] Remove some debug output. --- src/jobs/backupfilesystemjob.h | 2 +- src/util/externalcommand.cpp | 4 ---- src/util/externalcommandhelper.cpp | 16 ++++------------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/jobs/backupfilesystemjob.h b/src/jobs/backupfilesystemjob.h index 89f4fb6..67a9c92 100644 --- a/src/jobs/backupfilesystemjob.h +++ b/src/jobs/backupfilesystemjob.h @@ -22,7 +22,7 @@ #include "jobs/job.h" #include -#include + class Partition; class Device; class Report; diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 75e7e3e..e71fc98 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -25,7 +25,6 @@ #include "util/externalcommand.h" #include "util/report.h" -#include #include #include #include @@ -85,8 +84,6 @@ bool ExternalCommand::copyBlocks() if (cmd.isEmpty()) cmd = QStandardPaths::findExecutable(QStringLiteral("dd"), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); - qDebug() << "ExternalCommand::copyBlocks\n"; - KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.copyblockshelper")); action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); @@ -118,7 +115,6 @@ bool ExternalCommand::copyBlocks() m_Output = job->data()[QStringLiteral("output")].toByteArray(); setExitCode(job->data()[QStringLiteral("exitCode")].toInt()); - qDebug() << "ExternalCommand::copyBlocks finished"; emit finished(); return true; } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 1735f0f..d9e79f1 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -59,17 +59,14 @@ bool ExternalCommandHelper::writeData(QByteArray& buffer, qint64 offset) return true; } - qDebug() << "cmd exitCode "< 1000) { // const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); // const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; @@ -135,10 +129,8 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) if (rval) rval = writeData(buffer, lastBlockWriteOffset); - if (rval){ - qDebug() << "Percent 100"<<"\n"; + if (rval) emit progress(100); - } } From bf2a23dada582205fd330b1c7ed798b1194778f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 24 Jan 2018 15:45:19 +0000 Subject: [PATCH 023/175] Use copyjobs KAuth helper for other copying jobs too. --- src/jobs/backupfilesystemjob.cpp | 7 +--- src/jobs/job.cpp | 69 +++----------------------------- 2 files changed, 7 insertions(+), 69 deletions(-) diff --git a/src/jobs/backupfilesystemjob.cpp b/src/jobs/backupfilesystemjob.cpp index b1995f3..1999983 100644 --- a/src/jobs/backupfilesystemjob.cpp +++ b/src/jobs/backupfilesystemjob.cpp @@ -63,11 +63,8 @@ bool BackupFileSystemJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not open file system on source partition %1 for backup.", sourcePartition().deviceNode()); else if (!copyTarget.open()) report->line() << xi18nc("@info:progress", "Could not create backup file %1.", fileName()); - else { - ExternalCommand copyCmd(copySource, copyTarget, QProcess::SeparateChannels); - connect(©Cmd, &ExternalCommand::progress, this, [=] (int percent) { emit progress(percent); }, Qt::QueuedConnection); - rval = copyCmd.startCopyBlocks(-1); - } + else + rval = copyBlocks(*report, copyTarget, copySource); } jobFinished(*report, rval); diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index 192deb1..69a4532 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -24,6 +24,7 @@ #include "core/copysourcedevice.h" #include "core/copytargetdevice.h" +#include "util/externalcommand.h" #include "util/report.h" #include @@ -38,70 +39,10 @@ Job::Job() : bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) { - bool rval = true; - const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy - const qint64 blocksToCopy = source.length() / blockSize; - - qint64 readOffset = source.firstByte(); - qint64 writeOffset = target.firstByte(); - qint32 copyDirection = 1; - - if (target.firstByte() > source.firstByte()) { - readOffset = source.firstByte() + source.length() - blockSize; - writeOffset = target.firstByte() + source.length() - blockSize; - copyDirection = -1; - } - - report.line() << xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy, source.length(), readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left") : i18nc("direction: right", "right")); - - qint64 blocksCopied = 0; - - QByteArray buffer; - int percent = 0; - QTime t; - t.start(); - while (blocksCopied < blocksToCopy) { - if (!(rval = source.readData(buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) - break; - - if (!(rval = target.writeData(buffer, writeOffset + blockSize * blocksCopied * copyDirection))) - break; - - if (++blocksCopied * 100 / blocksToCopy != percent) { - percent = blocksCopied * 100 / blocksToCopy; - - if (percent % 5 == 0 && t.elapsed() > 1000) { - const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); - const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; - report.line() << xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); - } - emit progress(percent); - } - } - const qint64 lastBlock = source.length() % blockSize; - - // copy the remainder - if (rval && lastBlock > 0) { - Q_ASSERT(lastBlock < blockSize); - - const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : source.firstByte(); - const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : target.firstByte(); - - report.line() << xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); - - rval = source.readData(buffer, lastBlockReadOffset, lastBlock); - - if (rval) - rval = target.writeData(buffer, lastBlockWriteOffset); - - if (rval) - emit progress(100); - } - - - report.line() << xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", target.bytesWritten())); - - return rval; +// FIXME: report + ExternalCommand copyCmd(source, target, QProcess::SeparateChannels); + connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); + return copyCmd.startCopyBlocks(-1); } bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource) From b143c139e5b12eed0cfd010ae4e2ce5c439ed64b Mon Sep 17 00:00:00 2001 From: Huzaifa Faruqui Date: Sun, 28 Jan 2018 00:24:48 +0530 Subject: [PATCH 024/175] Fix Report in copyBlocks --- src/jobs/job.cpp | 10 ++++- src/jobs/job.h | 2 + src/util/CMakeLists.txt | 2 +- src/util/externalcommand.cpp | 6 ++- src/util/externalcommand.h | 7 +++- src/util/externalcommandhelper.cpp | 59 +++++++++++++++++++----------- 6 files changed, 60 insertions(+), 26 deletions(-) diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index 69a4532..09d0c58 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -29,19 +29,22 @@ #include #include +#include #include Job::Job() : + m_Report(nullptr), m_Status(Pending) { } bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) { -// FIXME: report + m_Report = &report; ExternalCommand copyCmd(source, target, QProcess::SeparateChannels); connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); + connect(©Cmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection); return copyCmd.startCopyBlocks(-1); } @@ -100,6 +103,11 @@ void Job::emitProgress(int i) emit progress(i); } +void Job::updateReport(const QVariantMap& reportString) +{ + m_Report->line() << reportString[QStringLiteral("report")].toString(); +} + Report* Job::jobStarted(Report& parent) { emit started(); diff --git a/src/jobs/job.h b/src/jobs/job.h index b4c46d5..b810a0b 100644 --- a/src/jobs/job.h +++ b/src/jobs/job.h @@ -81,6 +81,7 @@ public: } void emitProgress(int i); + void updateReport(const QVariantMap& reportString); protected: bool copyBlocks(Report& report, CopyTarget& target, CopySource& source); @@ -94,6 +95,7 @@ protected: } private: + Report *m_Report; JobStatus m_Status; }; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 439348e..c069dd2 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -18,7 +18,7 @@ set(UTIL_LIB_HDRS ) add_executable(kpmcore_externalcommand util/externalcommandhelper.cpp) -target_link_libraries(kpmcore_externalcommand KF5::Auth) +target_link_libraries(kpmcore_externalcommand KF5::Auth KF5::I18n) install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index e71fc98..bce47f6 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -88,7 +89,7 @@ bool ExternalCommand::copyBlocks() action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); arguments.insert(QStringLiteral("command"), cmd); - arguments.insert(QStringLiteral("sourceDevice"), m_Source->path() ); + arguments.insert(QStringLiteral("sourceDevice"), m_Source->path()); arguments.insert(QStringLiteral("targetDevice"), m_Target->path()); arguments.insert(QStringLiteral("blockSize"), blockSize); arguments.insert(QStringLiteral("blocksToCopy"), blocksToCopy); @@ -98,6 +99,7 @@ bool ExternalCommand::copyBlocks() arguments.insert(QStringLiteral("sourceFirstByte"), m_Source->firstByte()); arguments.insert(QStringLiteral("targetFirstByte"), m_Target->firstByte()); arguments.insert(QStringLiteral("lastBlock"), lastBlock); + arguments.insert(QStringLiteral("sourceLength"), m_Source->length()); action.setArguments(arguments); action.setTimeout(24 * 3600 * 1000); // set 1 day DBus timeout @@ -105,6 +107,8 @@ bool ExternalCommand::copyBlocks() KAuth::ExecuteJob *job = action.execute(); // TODO KF6:Use new signal-slot syntax connect(job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); + connect(job, &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); + if (!job->exec()) { qWarning() << "KAuth returned an error code: " << job->errorString(); // return false; diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 811b6f8..721b9d3 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -26,10 +26,10 @@ #include #include -#include #include -#include #include +#include +#include #include class Report; @@ -82,9 +82,12 @@ public: return m_Report; /**< @return pointer to the Report or nullptr */ } + void emitReport(const QVariantMap& report) { emit reportSignal(report); } + Q_SIGNALS: void progress(int); void finished(); + void reportSignal(const QVariantMap&); public Q_SLOTS: void emitProgress(KJob*, unsigned long percent) { emit progress(percent); }; diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index d9e79f1..c0e2c1e 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -19,6 +19,11 @@ #include #include +#include +#include + +#include + bool ExternalCommandHelper::readData(QByteArray& buffer, qint64 offset, qint64 size) { @@ -37,7 +42,7 @@ bool ExternalCommandHelper::readData(QByteArray& buffer, qint64 offset, qint64 s buffer = cmd.readAllStandardOutput(); return true; } - qDebug() << sourceDevice << " " << offset << " " << size << " cmd exitCode " << cmd.exitCode() << "\n"; + //qDebug() << sourceDevice << " " << offset << " " << size << " cmd exitCode " << cmd.exitCode() << "\n"; return false; } @@ -59,8 +64,7 @@ bool ExternalCommandHelper::writeData(QByteArray& buffer, qint64 offset) return true; } - qDebug() << "cmd exitCode " << cmd.exitCode() << "\n"; - + //qDebug() << "cmd exitCode " << cmd.exitCode() << "\n"; return false; } @@ -77,64 +81,77 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) qint64 lastBlock = args[QStringLiteral("lastBlock")].toInt(); qint64 sourceFirstByte = args[QStringLiteral("sourceFirstByte")].toInt(); qint64 targetFirstByte = args[QStringLiteral("targetFirstByte")].toInt(); + qint64 sourceLength = args[QStringLiteral("sourceLength")].toInt(); QStringList environment = args[QStringLiteral("environment")].toStringList(); ActionReply reply; - //connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); - cmd.setEnvironment(environment); + qint64 bytesWritten = 0; qint64 blocksCopied = 0; QByteArray buffer; int percent = 0; - //QTime t; + QTime t; + + t.start(); + + QVariantMap report; + + report[QStringLiteral("report")] = xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy, + sourceLength, readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left") + : i18nc("direction: right", "right")); + + HelperSupport::progressStep(report); + bool rval = true; - //qDebug() << command <<"\n"; + while (blocksCopied < blocksToCopy) { if (!(rval = readData(buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) break; if (!(rval = writeData(buffer, writeOffset + blockSize * blocksCopied * copyDirection))) break; - //qDebug() << "Exit code" < 1000) { - // const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); - // const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; - // report.line() << xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); - //} + if (percent % 5 == 0 && t.elapsed() > 1000) { + const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); + const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; + report[QStringLiteral("report")]= xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString()); + HelperSupport::progressStep(report); + } HelperSupport::progressStep(percent); } } - //const qint64 lastBlock = args[QStringLiteral("lastBlock")]; - // copy the remainder if (rval && lastBlock > 0) { Q_ASSERT(lastBlock < blockSize); const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte; const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte; - //report.line() << xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); - + report[QStringLiteral("report")]= xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); + HelperSupport::progressStep(report); rval = readData(buffer, lastBlockReadOffset, lastBlock); if (rval) rval = writeData(buffer, lastBlockWriteOffset); - if (rval) - emit progress(100); - + if (rval) { + HelperSupport::progressStep(100); + bytesWritten += buffer.size(); + } } - //report.line() << xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", target.bytesWritten())); + report[QStringLiteral("report")] = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten)); + HelperSupport::progressStep(report); return reply; } From 3a6aa4aaa0a3a9aaac23f601716837bf3337c5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 27 Jan 2018 13:19:35 +0000 Subject: [PATCH 025/175] Do not link to libatasmart. --- src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1fea707..bf10203 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,7 +42,6 @@ add_library(kpmcore SHARED ${kpmcore_SRCS}) target_link_libraries( kpmcore ${UUID_LIBRARIES} ${BLKID_LIBRARIES} - ${LIBATASMART_LIBRARIES} Qt5::DBus KF5::Auth KF5::I18n From c50006ed22eb95317133b94f0dbe62071c40bd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 16:12:11 +0000 Subject: [PATCH 026/175] Fix #include issues in smart code. CC: caiojcarvalho@gmail.com --- src/core/smartdiskinformation.h | 2 +- src/core/smartparser.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index cc79cf0..572168b 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -16,7 +16,7 @@ *************************************************************************/ #if !defined(KPMCORE_SMARTDISKINFORMATION_H) -#define SMARTDISKINFORMATION_H +#define KPMCORE_SMARTDISKINFORMATION_H #include #include diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index 5e4716a..ebd62da 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -22,6 +22,8 @@ #include "util/externalcommand.h" +#include + #include #include #include From 838150d4397d3def0ac52d6fcb98617189bb1bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 16:53:34 +0000 Subject: [PATCH 027/175] Do not use blkid cache. --- src/core/fstab.cpp | 11 +++-------- src/core/smartparser.cpp | 1 - 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index 2a5fb69..dd1e4a4 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -116,16 +116,11 @@ QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabP static QString findBlkIdDevice(const QString& token, const QString& value) { - blkid_cache cache; QString rval; - if (blkid_get_cache(&cache, nullptr) == 0) { - if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), &cache)) { - rval = QString::fromLocal8Bit(c); - free(c); - } - - blkid_put_cache(cache); + if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), nullptr)) { + rval = QString::fromLocal8Bit(c); + free(c); } return rval; diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index ebd62da..4dcf046 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -37,7 +37,6 @@ SmartParser::SmartParser(const QString &device_path) : m_DevicePath(device_path), m_DiskInformation(nullptr) { - } /** Initialize SmartParser data, retrieve the information from SMART JSON and initialize the disk information data */ From f98dbcc208738142ecdb57c42937c42369e7c27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 16:58:00 +0000 Subject: [PATCH 028/175] Only use libblkid on Linux. --- CMakeLists.txt | 7 ++++--- src/core/fstab.cpp | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1bd72d..e78da86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,9 +77,10 @@ add_definitions( ) kde_enable_exceptions() - -find_package(PkgConfig REQUIRED) -pkg_check_modules(BLKID REQUIRED blkid>=2.30) +if(LINUX) + find_package(PkgConfig REQUIRED) + pkg_check_modules(BLKID REQUIRED blkid>=2.30) +endif() include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index dd1e4a4..6a8e827 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -20,7 +20,9 @@ #include "core/fstab.h" #include "util/externalcommand.h" -#include +#if defined(Q_OS_LINUX) + #include +#endif #include #include @@ -118,10 +120,12 @@ static QString findBlkIdDevice(const QString& token, const QString& value) { QString rval; +#if defined(Q_OS_LINUX) if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), nullptr)) { rval = QString::fromLocal8Bit(c); free(c); } +#endif return rval; } From f2b7f2bd9b80e6b2f2bf7750a141858771af229b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 17:02:59 +0000 Subject: [PATCH 029/175] Use const char* instead of QString in Fstab::findBlkIdDevice Thansk to: Adriaan de Groot --- src/core/fstab.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index 6a8e827..ebbad89 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -32,7 +32,7 @@ #include static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode); -static QString findBlkIdDevice(const QString& token, const QString& value); +static QString findBlkIdDevice(const char *token, const QString& value); FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) : m_fsSpec(fsSpec) @@ -116,12 +116,12 @@ QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabP return mountPoints; } -static QString findBlkIdDevice(const QString& token, const QString& value) +static QString findBlkIdDevice(const char *token, const QString& value) { QString rval; #if defined(Q_OS_LINUX) - if (char* c = blkid_evaluate_tag(token.toLocal8Bit().constData(), value.toLocal8Bit().constData(), nullptr)) { + if (char* c = blkid_evaluate_tag(token, value.toLocal8Bit().constData(), nullptr)) { rval = QString::fromLocal8Bit(c); free(c); } @@ -135,16 +135,16 @@ static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QS m_entryType = FstabEntryType::comment; if (m_fsSpec.startsWith(QStringLiteral("UUID="))) { m_entryType = FstabEntryType::uuid; - m_deviceNode = findBlkIdDevice(QStringLiteral("UUID"), QString(m_fsSpec).remove(QStringLiteral("UUID="))); + m_deviceNode = findBlkIdDevice("UUID", QString(m_fsSpec).remove(QStringLiteral("UUID="))); } else if (m_fsSpec.startsWith(QStringLiteral("LABEL="))) { m_entryType = FstabEntryType::label; - m_deviceNode = findBlkIdDevice(QStringLiteral("LABEL"), QString(m_fsSpec).remove(QStringLiteral("LABEL="))); + m_deviceNode = findBlkIdDevice("LABEL", QString(m_fsSpec).remove(QStringLiteral("LABEL="))); } else if (m_fsSpec.startsWith(QStringLiteral("PARTUUID="))) { m_entryType = FstabEntryType::uuid; - m_deviceNode = findBlkIdDevice(QStringLiteral("PARTUUID"), QString(m_fsSpec).remove(QStringLiteral("PARTUUID="))); + m_deviceNode = findBlkIdDevice("PARTUUID", QString(m_fsSpec).remove(QStringLiteral("PARTUUID="))); } else if (m_fsSpec.startsWith(QStringLiteral("PARTLABEL="))) { m_entryType = FstabEntryType::label; - m_deviceNode = findBlkIdDevice(QStringLiteral("PARTLABEL"), QString(m_fsSpec).remove(QStringLiteral("PARTLABEL="))); + m_deviceNode = findBlkIdDevice("PARTLABEL", QString(m_fsSpec).remove(QStringLiteral("PARTLABEL="))); } else if (m_fsSpec.startsWith(QStringLiteral("/"))) { m_entryType = FstabEntryType::deviceNode; m_deviceNode = m_fsSpec; From 7e60df68bd87496e45e018af9727d5825e71ae42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 17:08:05 +0000 Subject: [PATCH 030/175] Do not expose libparted backend on non Linux systems. --- src/plugins/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index c5a982a..58daacd 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -17,11 +17,13 @@ install(FILES pmcorebackendplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) -option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) +if(LINUX) + option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) -if (PARTMAN_LIBPARTEDBACKEND) - add_subdirectory(libparted) -endif (PARTMAN_LIBPARTEDBACKEND) + if (PARTMAN_LIBPARTEDBACKEND) + add_subdirectory(libparted) + endif (PARTMAN_LIBPARTEDBACKEND) +endif(LINUX) option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) From 4870587339b5f6de5a951146c607297b99c3b7e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 31 Jan 2018 18:49:21 +0000 Subject: [PATCH 031/175] Set sfdisk backend as default. --- src/backend/corebackendmanager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index 7460136..b85e9e9 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -51,7 +51,7 @@ public: * @return the name of the default backend plugin */ static QString defaultBackendName() { - return QStringLiteral("pmlibpartedbackendplugin"); + return QStringLiteral("pmsfdiskbackendplugin"); } /** From 5c307c1cc76bd65b1ddf6cff5170624b1ddcf8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 2 Feb 2018 18:33:35 +0000 Subject: [PATCH 032/175] Use toLongLong in KAuth helper. Otherwise all integers simply overflow. --- src/util/externalcommandhelper.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index c0e2c1e..856c099 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -71,17 +71,17 @@ bool ExternalCommandHelper::writeData(QByteArray& buffer, qint64 offset) ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) { command = args[QStringLiteral("command")].toString(); - qint64 blockSize = args[QStringLiteral("blockSize")].toInt(); - qint64 blocksToCopy = args[QStringLiteral("blocksToCopy")].toInt(); - qint64 readOffset = args[QStringLiteral("readOffset")].toInt(); - qint64 writeOffset = args[QStringLiteral("writeOffset")].toInt(); - qint32 copyDirection = args[QStringLiteral("copyDirection")].toInt(); + qint64 blockSize = args[QStringLiteral("blockSize")].toLongLong(); + qint64 blocksToCopy = args[QStringLiteral("blocksToCopy")].toLongLong(); + qint64 readOffset = args[QStringLiteral("readOffset")].toLongLong(); + qint64 writeOffset = args[QStringLiteral("writeOffset")].toLongLong(); + qint32 copyDirection = args[QStringLiteral("copyDirection")].toLongLong(); sourceDevice = args[QStringLiteral("sourceDevice")].toString(); targetDevice = args[QStringLiteral("targetDevice")].toString(); - qint64 lastBlock = args[QStringLiteral("lastBlock")].toInt(); - qint64 sourceFirstByte = args[QStringLiteral("sourceFirstByte")].toInt(); - qint64 targetFirstByte = args[QStringLiteral("targetFirstByte")].toInt(); - qint64 sourceLength = args[QStringLiteral("sourceLength")].toInt(); + qint64 lastBlock = args[QStringLiteral("lastBlock")].toLongLong(); + qint64 sourceFirstByte = args[QStringLiteral("sourceFirstByte")].toLongLong(); + qint64 targetFirstByte = args[QStringLiteral("targetFirstByte")].toLongLong(); + qint64 sourceLength = args[QStringLiteral("sourceLength")].toLongLong(); QStringList environment = args[QStringLiteral("environment")].toStringList(); From f426f59799296b8565fb4c2ac136aecac2174f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 3 Feb 2018 15:57:47 +0000 Subject: [PATCH 033/175] Use QFile for writing data in ExternalCommandHelper::writeData dd works much slower when writing to files, especially files on SSD. Thanks to Huzaifa Faruqui for suggestion. --- src/util/externalcommandhelper.cpp | 48 ++++++++++++++---------------- src/util/externalcommandhelper.h | 5 ++-- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 856c099..88e0ac5 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -18,6 +18,7 @@ #include "externalcommandhelper.h" #include +#include #include #include #include @@ -25,7 +26,7 @@ #include -bool ExternalCommandHelper::readData(QByteArray& buffer, qint64 offset, qint64 size) +bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size) { QStringList arguments = { QStringLiteral("skip=") + QString::number(offset), @@ -46,26 +47,24 @@ bool ExternalCommandHelper::readData(QByteArray& buffer, qint64 offset, qint64 s return false; } -bool ExternalCommandHelper::writeData(QByteArray& buffer, qint64 offset) +bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, qint64 offset) { - QStringList arguments = { - QStringLiteral("of=") + targetDevice, - QStringLiteral("seek=") + QString::number(offset), - QStringLiteral("bs=1M"), - QStringLiteral("oflag=seek_bytes"), - QStringLiteral("conv=fsync") }; - - cmd.start(command, arguments); - cmd.write(buffer); - cmd.closeWriteChannel(); - cmd.waitForFinished(-1); - - if (cmd.exitCode() == 0 ) { - return true; + QFile device(targetDevice); + if (!device.open(QFile::WriteOnly | QFile::Unbuffered)) { + qCritical() << xi18n("Could not open device %1 for writing.", targetDevice); + return false; } - //qDebug() << "cmd exitCode " << cmd.exitCode() << "\n"; - return false; + if (!device.seek(offset)) { + qCritical() << xi18n("Could not seek position %1 on device %1.", targetDevice); + return false; + } + + if (device.write(buffer) != buffer.size()) { + qCritical() << xi18n("Could not write to device %1.", targetDevice); + return false; + } + return true; } ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) @@ -76,8 +75,8 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) qint64 readOffset = args[QStringLiteral("readOffset")].toLongLong(); qint64 writeOffset = args[QStringLiteral("writeOffset")].toLongLong(); qint32 copyDirection = args[QStringLiteral("copyDirection")].toLongLong(); - sourceDevice = args[QStringLiteral("sourceDevice")].toString(); - targetDevice = args[QStringLiteral("targetDevice")].toString(); + QString sourceDevice = args[QStringLiteral("sourceDevice")].toString(); + QString targetDevice = args[QStringLiteral("targetDevice")].toString(); qint64 lastBlock = args[QStringLiteral("lastBlock")].toLongLong(); qint64 sourceFirstByte = args[QStringLiteral("sourceFirstByte")].toLongLong(); qint64 targetFirstByte = args[QStringLiteral("targetFirstByte")].toLongLong(); @@ -109,10 +108,10 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) bool rval = true; while (blocksCopied < blocksToCopy) { - if (!(rval = readData(buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) + if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) break; - if (!(rval = writeData(buffer, writeOffset + blockSize * blocksCopied * copyDirection))) + if (!(rval = writeData(targetDevice, buffer, writeOffset + blockSize * blocksCopied * copyDirection))) break; bytesWritten += buffer.size(); @@ -120,7 +119,6 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) if (++blocksCopied * 100 / blocksToCopy != percent) { percent = blocksCopied * 100 / blocksToCopy; - // FIXME if (percent % 5 == 0 && t.elapsed() > 1000) { const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (t.elapsed() / 1000); const qint64 estSecsLeft = (100 - percent) * t.elapsed() / percent / 1000; @@ -139,10 +137,10 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte; report[QStringLiteral("report")]= xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset); HelperSupport::progressStep(report); - rval = readData(buffer, lastBlockReadOffset, lastBlock); + rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock); if (rval) - rval = writeData(buffer, lastBlockWriteOffset); + rval = writeData(targetDevice, buffer, lastBlockWriteOffset); if (rval) { HelperSupport::progressStep(100); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 5d2d28d..a7ff29b 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -34,8 +34,8 @@ Q_SIGNALS: void progress(int); public: - bool readData(QByteArray& buffer, qint64 offset, qint64 size); - bool writeData(QByteArray& buffer, qint64 offset); + bool readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size); + bool writeData(QString& targetDevice, QByteArray& buffer, qint64 offset); public Q_SLOTS: ActionReply start(const QVariantMap& args); @@ -46,7 +46,6 @@ private: QString command; QString sourceDevice; - QString targetDevice; QProcess cmd; // QByteArray output; }; From b35c21ed71971c32573cca1856634432d20c9430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 4 Feb 2018 13:44:55 +0000 Subject: [PATCH 034/175] Fix an out of order compile warning. Initialization should happen in the same order as variables are declared. CC: huzaifafaruqui@gmail.com --- src/util/externalcommand.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index bce47f6..da0f51f 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -39,9 +39,9 @@ ExternalCommand::ExternalCommand(CopySource& source, CopyTarget& target,const QProcess::ProcessChannelMode processChannelMode) : + m_ExitCode(-1), m_Source(&source), - m_Target(&target), - m_ExitCode(-1) + m_Target(&target) { setup(processChannelMode); } From 11e435657a68297d6040ba516c142b4d964e75e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 4 Feb 2018 16:14:59 +0000 Subject: [PATCH 035/175] Do not build libparted backend. --- src/plugins/CMakeLists.txt | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 58daacd..651b722 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -17,20 +17,22 @@ install(FILES pmcorebackendplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) +#if(LINUX) +# option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) + +# if (PARTMAN_LIBPARTEDBACKEND) +# add_subdirectory(libparted) +# endif (PARTMAN_LIBPARTEDBACKEND) +#endif(LINUX) + if(LINUX) - option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) + option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) - if (PARTMAN_LIBPARTEDBACKEND) - add_subdirectory(libparted) - endif (PARTMAN_LIBPARTEDBACKEND) + if (PARTMAN_SFDISKBACKEND) + add_subdirectory(sfdisk) + endif (PARTMAN_SFDISKBACKEND) endif(LINUX) -option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) - -if (PARTMAN_SFDISKBACKEND) - add_subdirectory(sfdisk) -endif (PARTMAN_SFDISKBACKEND) - option(PARTMAN_DUMMYBACKEND "Build the dummy backend plugin." ON) if (PARTMAN_DUMMYBACKEND) From aa23fc11684f99f3c36066bbaeaa37bb42323c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 4 Feb 2018 19:11:25 +0000 Subject: [PATCH 036/175] cmake does not define LINUX variable. --- src/plugins/CMakeLists.txt | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 651b722..1311ebb 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -17,21 +17,17 @@ install(FILES pmcorebackendplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) -#if(LINUX) -# option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) +#option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) -# if (PARTMAN_LIBPARTEDBACKEND) -# add_subdirectory(libparted) -# endif (PARTMAN_LIBPARTEDBACKEND) -#endif(LINUX) +#if (PARTMAN_LIBPARTEDBACKEND) +# add_subdirectory(libparted) +#endif (PARTMAN_LIBPARTEDBACKEND) -if(LINUX) - option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) +option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) - if (PARTMAN_SFDISKBACKEND) - add_subdirectory(sfdisk) - endif (PARTMAN_SFDISKBACKEND) -endif(LINUX) +if (PARTMAN_SFDISKBACKEND) + add_subdirectory(sfdisk) +endif (PARTMAN_SFDISKBACKEND) option(PARTMAN_DUMMYBACKEND "Build the dummy backend plugin." ON) From af6c345210a0ca81b215c8e66ddb4c0b36eef9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 4 Feb 2018 19:17:34 +0000 Subject: [PATCH 037/175] Use CMAKE_SYSTEM_NAME to check whether we are running on Linux. --- CMakeLists.txt | 2 +- src/plugins/CMakeLists.txt | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e78da86..f6b5a63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ add_definitions( ) kde_enable_exceptions() -if(LINUX) +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(PkgConfig REQUIRED) pkg_check_modules(BLKID REQUIRED blkid>=2.30) endif() diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 1311ebb..fb5186f 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -23,11 +23,13 @@ install(FILES pmcorebackendplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR # add_subdirectory(libparted) #endif (PARTMAN_LIBPARTEDBACKEND) -option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) -if (PARTMAN_SFDISKBACKEND) - add_subdirectory(sfdisk) -endif (PARTMAN_SFDISKBACKEND) + if (PARTMAN_SFDISKBACKEND) + add_subdirectory(sfdisk) + endif (PARTMAN_SFDISKBACKEND) +endif() option(PARTMAN_DUMMYBACKEND "Build the dummy backend plugin." ON) From b79f713ed8421d2a7c88021976653035db243098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 5 Feb 2018 12:46:10 +0000 Subject: [PATCH 038/175] Fix ExternalCommandHelper::writeData function. QFile::open needs QIODevice::Append flag. --- src/util/externalcommandhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 88e0ac5..14bdc44 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -50,7 +50,7 @@ bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, qint64 offset) { QFile device(targetDevice); - if (!device.open(QFile::WriteOnly | QFile::Unbuffered)) { + if (!device.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered)) { qCritical() << xi18n("Could not open device %1 for writing.", targetDevice); return false; } From 00d47c64179a21088358cf581202c0f50096f4ec Mon Sep 17 00:00:00 2001 From: Huzaifa Faruqui Date: Mon, 5 Feb 2018 12:58:37 +0000 Subject: [PATCH 039/175] Use QFile for ExternalCommandHelper::readData. --- src/util/externalcommandhelper.cpp | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 14bdc44..3d77b81 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -28,23 +28,26 @@ bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size) { - QStringList arguments = { - QStringLiteral("skip=") + QString::number(offset), - QStringLiteral("bs=") + QString::number(size), - QStringLiteral("count=1"), - QStringLiteral("iflag=skip_bytes"), - QStringLiteral("if=") + sourceDevice - }; + QFile device(sourceDevice); - cmd.start(command, arguments); - cmd.waitForFinished(-1); - - if (cmd.exitCode() == 0) { - buffer = cmd.readAllStandardOutput(); - return true; + if (!device.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) { + qCritical() << xi18n("Could not open device %1 for reading.", sourceDevice); + return false; } - //qDebug() << sourceDevice << " " << offset << " " << size << " cmd exitCode " << cmd.exitCode() << "\n"; - return false; + + if (!device.seek(offset)) { + qCritical() << xi18n("Could not seek position %1 on device %1.", sourceDevice); + return false; + } + + buffer = device.read(size); + + if (size != buffer.size()) { + qCritical() << xi18n("Could not read from device %1.", sourceDevice); + return false; + } + + return true; } bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, qint64 offset) From 06139c85aca33335214b09a5ccb2927f2d060fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 6 Feb 2018 16:24:32 +0000 Subject: [PATCH 040/175] Remove unused function argument in startCopyBlocks. --- src/jobs/job.cpp | 2 +- src/util/externalcommand.cpp | 4 +--- src/util/externalcommand.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index 09d0c58..e1b913a 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -45,7 +45,7 @@ bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) ExternalCommand copyCmd(source, target, QProcess::SeparateChannels); connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); connect(©Cmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection); - return copyCmd.startCopyBlocks(-1); + return copyCmd.startCopyBlocks(); } bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index da0f51f..4d8f66a 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -48,10 +48,8 @@ ExternalCommand::ExternalCommand(CopySource& source, CopyTarget& target,const QP /** Starts copyBlocks command. - @param timeout timeout to wait for the process to start - @return true on success */ -bool ExternalCommand::startCopyBlocks(int timeout) +bool ExternalCommand::startCopyBlocks() { this->moveToThread(CoreBackendManager::self()->kauthThread()); QTimer::singleShot(0, this, &ExternalCommand::copyBlocks); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 721b9d3..3acace8 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -61,7 +61,7 @@ public: void setArgs(const QStringList& args) { m_Args = args; } /**< @param args the new arguments */ bool write(const QByteArray& input); /**< @param input the input for the program */ - bool startCopyBlocks(int timeout =30000); + bool startCopyBlocks(); bool start(int timeout = 30000); bool waitFor(int timeout = 30000); bool run(int timeout = 30000); From ac6dc0eb87ae5080914a54763486cafd329ae140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 6 Feb 2018 16:48:02 +0000 Subject: [PATCH 041/175] Remove backend readData/writeData functions. --- src/backend/corebackenddevice.h | 17 ----------- src/core/copysource.h | 1 - src/core/copysourcedevice.cpp | 16 ---------- src/core/copysourcedevice.h | 1 - src/core/copysourcefile.cpp | 15 --------- src/core/copysourcefile.h | 1 - src/core/copysourceshred.cpp | 14 --------- src/core/copysourceshred.h | 1 - src/core/copytarget.h | 1 - src/core/copytargetdevice.cpp | 19 ------------ src/core/copytargetdevice.h | 1 - src/core/copytargetfile.cpp | 18 ----------- src/core/copytargetfile.h | 1 - src/plugins/dummy/dummydevice.cpp | 23 -------------- src/plugins/dummy/dummydevice.h | 3 -- src/plugins/libparted/libparteddevice.cpp | 20 ------------ src/plugins/libparted/libparteddevice.h | 3 -- src/plugins/sfdisk/sfdiskdevice.cpp | 37 ----------------------- src/plugins/sfdisk/sfdiskdevice.h | 3 -- src/util/externalcommandhelper.cpp | 14 ++++++++- 20 files changed, 13 insertions(+), 196 deletions(-) diff --git a/src/backend/corebackenddevice.h b/src/backend/corebackenddevice.h index 600adc6..b3c3126 100644 --- a/src/backend/corebackenddevice.h +++ b/src/backend/corebackenddevice.h @@ -91,23 +91,6 @@ public: */ virtual bool createPartitionTable(Report& report, const PartitionTable& ptable) = 0; - /** - * Read data from an opened device into a buffer. - * @param buffer the buffer to write the read data to - * @param offset offset byte where to start reading on the device - * @param size the number of bytes to read - * @return true on success - */ - virtual bool readData(QByteArray& buffer, qint64 offset, qint64 size) = 0; - - /** - * Write data from a buffer to an exclusively opened device. - * @param buffer the buffer with the data - * @param offset offset byte where to start writing to the device - * @return true on success - */ - virtual bool writeData(QByteArray& buffer, qint64 offset) = 0; - protected: void setExclusive(bool b) { m_Exclusive = b; diff --git a/src/core/copysource.h b/src/core/copysource.h index 3f25e7f..f8f36b2 100644 --- a/src/core/copysource.h +++ b/src/core/copysource.h @@ -43,7 +43,6 @@ protected: public: virtual bool open() = 0; virtual QString path() const = 0; - virtual bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) = 0; virtual qint64 length() const = 0; virtual bool overlaps(const CopyTarget& target) const = 0; diff --git a/src/core/copysourcedevice.cpp b/src/core/copysourcedevice.cpp index 3b91744..9754a0d 100644 --- a/src/core/copysourcedevice.cpp +++ b/src/core/copysourcedevice.cpp @@ -63,22 +63,6 @@ qint64 CopySourceDevice::length() const return lastByte() - firstByte() + 1; } -/** Reads a given number of bytes from the Device into the given buffer. - - Note that @p readOffset must be greater or equal than zero. - - @param buffer the buffer to store the read bytes in - @param readOffset the offset to begin reading - @param size the number of bytes to read - - @return true if successful -*/ -bool CopySourceDevice::readData(QByteArray& buffer, qint64 readOffset, qint64 size) -{ - Q_ASSERT(readOffset >= 0); - return m_BackendDevice->readData(buffer, readOffset, size); -} - /** Checks if this CopySourceDevice overlaps with the given CopyTarget @param target the CopyTarget to check overlapping with @return true if overlaps diff --git a/src/core/copysourcedevice.h b/src/core/copysourcedevice.h index 04f1734..bfdbd45 100644 --- a/src/core/copysourcedevice.h +++ b/src/core/copysourcedevice.h @@ -45,7 +45,6 @@ public: public: bool open() override; - bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override; qint64 length() const override; bool overlaps(const CopyTarget& target) const override; diff --git a/src/core/copysourcefile.cpp b/src/core/copysourcefile.cpp index 936aec0..40c3a15 100644 --- a/src/core/copysourcefile.cpp +++ b/src/core/copysourcefile.cpp @@ -45,18 +45,3 @@ qint64 CopySourceFile::length() const { return QFileInfo(file()).size(); } - -/** Reads the given number of bytes from the file into the given buffer. - @param buffer buffer to store the bytes read in - @param readOffset offset where to begin reading - @param size the number of bytes to read - @return true on success -*/ -bool CopySourceFile::readData(QByteArray& buffer, qint64 readOffset, qint64 size) -{ - if (!file().seek(readOffset)) - return false; - - buffer = file().read(size); - return !buffer.isEmpty(); -} diff --git a/src/core/copysourcefile.h b/src/core/copysourcefile.h index 0ff8ff7..3a5cebd 100644 --- a/src/core/copysourcefile.h +++ b/src/core/copysourcefile.h @@ -40,7 +40,6 @@ public: public: bool open() override; - bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override; qint64 length() const override; bool overlaps(const CopyTarget&) const override { diff --git a/src/core/copysourceshred.cpp b/src/core/copysourceshred.cpp index b8d708e..91ab354 100644 --- a/src/core/copysourceshred.cpp +++ b/src/core/copysourceshred.cpp @@ -43,17 +43,3 @@ qint64 CopySourceShred::length() const { return size(); } - -/** Reads the given number of bytes from the source into the given buffer. - @param buffer buffer to store the data read in - @param readOffset offset where to begin reading (unused) - @param size the number of bytes to read - @return true on success -*/ -bool CopySourceShred::readData(QByteArray& buffer, qint64 readOffset, qint64 size) -{ - Q_UNUSED(readOffset); - - buffer = sourceFile().read(size); - return !buffer.isEmpty(); -} diff --git a/src/core/copysourceshred.h b/src/core/copysourceshred.h index e293531..a181100 100644 --- a/src/core/copysourceshred.h +++ b/src/core/copysourceshred.h @@ -39,7 +39,6 @@ public: public: bool open() override; - bool readData(QByteArray& buffer, qint64 readOffset, qint64 size) override; qint64 length() const override; bool overlaps(const CopyTarget&) const override { diff --git a/src/core/copytarget.h b/src/core/copytarget.h index 97385a1..92324f6 100644 --- a/src/core/copytarget.h +++ b/src/core/copytarget.h @@ -41,7 +41,6 @@ protected: public: virtual bool open() = 0; - virtual bool writeData(QByteArray& buffer, qint64 writeOffset) = 0; virtual qint64 firstByte() const = 0; virtual qint64 lastByte() const = 0; virtual QString path() const = 0; diff --git a/src/core/copytargetdevice.cpp b/src/core/copytargetdevice.cpp index 92e67f2..2ad9a02 100644 --- a/src/core/copytargetdevice.cpp +++ b/src/core/copytargetdevice.cpp @@ -52,25 +52,6 @@ bool CopyTargetDevice::open() return m_BackendDevice != nullptr; } -/** Writes the given number of bytes to the Device. - - Note that @p writeOffset must be greater or equal than zero. - - @param buffer the data to write - @param writeOffset where to start writing on the Device - @return true on success -*/ -bool CopyTargetDevice::writeData(QByteArray& buffer, qint64 writeOffset) -{ - Q_ASSERT(writeOffset >= 0); - bool rval = m_BackendDevice->writeData(buffer, writeOffset); - - if (rval) - setBytesWritten(bytesWritten() + buffer.size()); - - return rval; -} - QString CopyTargetDevice::path() const { return m_Device.deviceNode(); diff --git a/src/core/copytargetdevice.h b/src/core/copytargetdevice.h index 556b75e..f7021d2 100644 --- a/src/core/copytargetdevice.h +++ b/src/core/copytargetdevice.h @@ -46,7 +46,6 @@ public: public: bool open() override; - bool writeData(QByteArray& buffer, qint64 writeOffset) override; qint64 firstByte() const override { return m_FirstByte; /**< @return the first byte to write to */ } diff --git a/src/core/copytargetfile.cpp b/src/core/copytargetfile.cpp index 508f9b2..bd87637 100644 --- a/src/core/copytargetfile.cpp +++ b/src/core/copytargetfile.cpp @@ -33,21 +33,3 @@ bool CopyTargetFile::open() { return file().open(QIODevice::WriteOnly | QIODevice::Truncate); } - -/** Writes the given number of bytes from the given buffer to the file. - @param buffer the data to write - @param writeOffset where in the file to start writing - @return true on success -*/ -bool CopyTargetFile::writeData(QByteArray& buffer, qint64 writeOffset) -{ - if (!file().seek(writeOffset)) - return false; - - bool rval = file().write(buffer) == buffer.size(); - - if (rval) - setBytesWritten(bytesWritten() + buffer.size()); - - return rval; -} diff --git a/src/core/copytargetfile.h b/src/core/copytargetfile.h index 17ecff2..258a403 100644 --- a/src/core/copytargetfile.h +++ b/src/core/copytargetfile.h @@ -40,7 +40,6 @@ public: public: bool open() override; - bool writeData(QByteArray& buffer, qint64 writeOffset) override; qint64 firstByte() const override { return 0; /**< @return always 0 for a file */ diff --git a/src/plugins/dummy/dummydevice.cpp b/src/plugins/dummy/dummydevice.cpp index 92c2de7..d2b43e9 100644 --- a/src/plugins/dummy/dummydevice.cpp +++ b/src/plugins/dummy/dummydevice.cpp @@ -66,26 +66,3 @@ bool DummyDevice::createPartitionTable(Report& report, const PartitionTable& pta return true; } - -bool DummyDevice::readData(QByteArray& buffer, qint64 offset, qint64 size) -{ - Q_UNUSED(buffer); - Q_UNUSED(offset); - Q_UNUSED(size); - - if (!isExclusive()) - return false; - - return true; -} - -bool DummyDevice::writeData(QByteArray& buffer, qint64 offset) -{ - Q_UNUSED(buffer); - Q_UNUSED(offset); - - if (!isExclusive()) - return false; - - return true; -} diff --git a/src/plugins/dummy/dummydevice.h b/src/plugins/dummy/dummydevice.h index 9493365..6895e65 100644 --- a/src/plugins/dummy/dummydevice.h +++ b/src/plugins/dummy/dummydevice.h @@ -44,9 +44,6 @@ public: CoreBackendPartitionTable* openPartitionTable() override; bool createPartitionTable(Report& report, const PartitionTable& ptable) override; - - bool readData(QByteArray& buffer, qint64 offset, qint64 size) override; - bool writeData(QByteArray& buffer, qint64 offset) override; }; #endif diff --git a/src/plugins/libparted/libparteddevice.cpp b/src/plugins/libparted/libparteddevice.cpp index 6354b58..d97e41c 100644 --- a/src/plugins/libparted/libparteddevice.cpp +++ b/src/plugins/libparted/libparteddevice.cpp @@ -110,23 +110,3 @@ bool LibPartedDevice::createPartitionTable(Report& report, const PartitionTable& return LibPartedPartitionTable::commit(disk); } - -bool LibPartedDevice::readData(QByteArray& buffer, qint64 offset, qint64 size) -{ - if (!isExclusive()) - return false; - - void *data = malloc(size); - bool rval = ped_device_read(pedDevice(), data, offset / pedDevice()->sector_size, size / pedDevice()->sector_size); - buffer = QByteArray(static_cast(data), size); - free(data); - return rval; -} - -bool LibPartedDevice::writeData(QByteArray& buffer, qint64 offset) -{ - if (!isExclusive()) - return false; - - return ped_device_write(pedDevice(), static_cast(buffer.constData()), offset / pedDevice()->sector_size, buffer.size() / pedDevice()->sector_size); -} diff --git a/src/plugins/libparted/libparteddevice.h b/src/plugins/libparted/libparteddevice.h index c8d98c0..dc8f16a 100644 --- a/src/plugins/libparted/libparteddevice.h +++ b/src/plugins/libparted/libparteddevice.h @@ -47,9 +47,6 @@ public: bool createPartitionTable(Report& report, const PartitionTable& ptable) override; - bool readData(QByteArray& buffer, qint64 offset, qint64 size) override; - bool writeData(QByteArray& buffer, qint64 offset) override; - protected: PedDevice* pedDevice() { return m_PedDevice; diff --git a/src/plugins/sfdisk/sfdiskdevice.cpp b/src/plugins/sfdisk/sfdiskdevice.cpp index c8ce382..7dfc248 100644 --- a/src/plugins/sfdisk/sfdiskdevice.cpp +++ b/src/plugins/sfdisk/sfdiskdevice.cpp @@ -79,40 +79,3 @@ bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& pt return false; } - -bool SfdiskDevice::readData(QByteArray& buffer, qint64 offset, qint64 size) -{ - if (!isExclusive()) - return false; - - ExternalCommand ddCommand(QStringLiteral("dd"), { - QStringLiteral("skip=") + QString::number(offset), - QStringLiteral("bs=") + QString::number(size), - QStringLiteral("count=1"), - QStringLiteral("iflag=skip_bytes"), - QStringLiteral("if=") + m_device->deviceNode() }, QProcess::SeparateChannels); - if (ddCommand.run(-1) && ddCommand.exitCode() == 0) { - buffer = ddCommand.rawOutput(); - return true; - } - - return false; -} - -bool SfdiskDevice::writeData(QByteArray& buffer, qint64 offset) -{ - if (!isExclusive()) - return false; - - ExternalCommand ddCommand(QStringLiteral("dd"), { - QStringLiteral("of=") + m_device->deviceNode(), - QStringLiteral("seek=") + QString::number(offset), - QStringLiteral("bs=1M"), - QStringLiteral("oflag=seek_bytes"), - QStringLiteral("conv=fsync") }, QProcess::SeparateChannels); - if ( ddCommand.write(buffer) && ddCommand.start(-1) && ddCommand.waitFor() && ddCommand.exitCode() == 0 ) { - return true; - } - - return false; -} diff --git a/src/plugins/sfdisk/sfdiskdevice.h b/src/plugins/sfdisk/sfdiskdevice.h index aeab327..096dd74 100644 --- a/src/plugins/sfdisk/sfdiskdevice.h +++ b/src/plugins/sfdisk/sfdiskdevice.h @@ -46,9 +46,6 @@ public: bool createPartitionTable(Report& report, const PartitionTable& ptable) override; - bool readData(QByteArray& buffer, qint64 offset, qint64 size) override; - bool writeData(QByteArray& buffer, qint64 offset) override; - private: const Device *m_device; }; diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 3d77b81..3694e5b 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -25,7 +25,13 @@ #include - +/** Reads the given number of bytes from the sourceDevice into the given buffer. + @param sourceDevice device or file to read from + @param buffer buffer to store the bytes read in + @param offset offset where to begin reading + @param size the number of bytes to read + @return true on success +*/ bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size) { QFile device(sourceDevice); @@ -50,6 +56,12 @@ bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, return true; } +/** Writes the data from buffer to a given device or file. + @param targetDevice 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(QString &targetDevice, QByteArray& buffer, qint64 offset) { QFile device(targetDevice); From 72da1109966690524aebf31d37dc4ff517a03adc Mon Sep 17 00:00:00 2001 From: Huzaifa Faruqui Date: Tue, 6 Feb 2018 22:32:26 +0530 Subject: [PATCH 042/175] Fix copyblocks exit status check --- src/jobs/job.cpp | 6 +++++- src/util/externalcommand.cpp | 6 +++--- src/util/externalcommandhelper.cpp | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index e1b913a..453521b 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -45,7 +45,11 @@ bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) ExternalCommand copyCmd(source, target, QProcess::SeparateChannels); connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); connect(©Cmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection); - return copyCmd.startCopyBlocks(); + if (copyCmd.startCopyBlocks() && copyCmd.exitCode() == 0) { + return true; + } + + return false; } bool Job::rollbackCopyBlocks(Report& report, CopyTarget& origTarget, CopySource& origSource) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 4d8f66a..8dfb445 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -114,11 +114,11 @@ bool ExternalCommand::copyBlocks() return false; } - m_Output = job->data()[QStringLiteral("output")].toByteArray(); - setExitCode(job->data()[QStringLiteral("exitCode")].toInt()); + rval = job->data()[QStringLiteral("success")].toInt(); + setExitCode(!rval); emit finished(); - return true; + return rval; } /** Creates a new ExternalCommand instance without Report. diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 3694e5b..00d4e0e 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -166,6 +166,8 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) report[QStringLiteral("report")] = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten)); HelperSupport::progressStep(report); + reply.addData(QStringLiteral("success"), rval); + return reply; } From 645e16bb20feb6602de051f1089cc365b22e823f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 19 Mar 2018 11:33:20 +0100 Subject: [PATCH 043/175] WIP: add some experimental code where helper is used as daemon Caveats: * copyblocks are not converted yet, but should be similar. * There is no signaling back to main application which tells when even loop has started, so after password is entered, you need to click F5 to rescan devices * There are some security checks but are they sufficient --- src/backend/corebackendmanager.cpp | 20 ++++++ src/backend/corebackendmanager.h | 13 ++++ src/util/CMakeLists.txt | 15 ++++- src/util/externalcommand.cpp | 53 +++++++--------- src/util/externalcommandhelper.cpp | 63 ++++++++++++++----- src/util/externalcommandhelper.h | 16 +++-- .../org.kde.kpmcore.externalcommand.actions | 12 +--- src/util/org.kde.kpmcore.helperinterface.conf | 16 +++++ 8 files changed, 146 insertions(+), 62 deletions(-) create mode 100644 src/util/org.kde.kpmcore.helperinterface.conf diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 5014252..f52b4aa 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -20,12 +20,16 @@ #include "backend/corebackendmanager.h" #include "backend/corebackend.h" +#include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -59,6 +63,19 @@ QVector CoreBackendManager::list() const return KPluginLoader::findPlugins(QString(), filter); } +void CoreBackendManager::startExternalCommandHelper() +{ + KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); + action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); + action.setTimeout(10 * 24 * 3600 * 1000); // 10 days + QVariantMap arguments; + m_Uuid = QUuid::createUuid().toString(); + arguments.insert(QStringLiteral("callerUuid"), Uuid()); + action.setArguments(arguments); + KAuth::ExecuteJob *job = action.execute(); + job->start(); +} + bool CoreBackendManager::load(const QString& name) { if (backend()) @@ -81,6 +98,9 @@ bool CoreBackendManager::load(const QString& name) backend()->setId(id); backend()->setVersion(version); qDebug() << "Loaded backend plugin: " << backend()->id(); + + startExternalCommandHelper(); + return true; } diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index b85e9e9..d4f1351 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -21,6 +21,7 @@ #include "util/libpartitionmanagerexport.h" +#include #include class QThread; @@ -85,9 +86,21 @@ public: return m_KAuthThread; } + /** + * @return a pointer to the currently loaded backend + */ + QString& Uuid() { + return m_Uuid; + } + +private: + void startExternalCommandHelper(); + private: CoreBackend* m_Backend; QThread* m_KAuthThread; + + QString m_Uuid; }; #endif diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index c069dd2..22957f7 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -17,9 +17,22 @@ set(UTIL_LIB_HDRS util/report.h ) +qt5_generate_dbus_interface( + externalcommand_interface.h + org.kde.kpmcore.externalcommand.xml +) + add_executable(kpmcore_externalcommand util/externalcommandhelper.cpp) -target_link_libraries(kpmcore_externalcommand KF5::Auth KF5::I18n) + +target_link_libraries(kpmcore_externalcommand + Qt5::Core + Qt5::DBus + KF5::Auth + KF5::I18n +) + install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) +install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d ) kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root) kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 8dfb445..ba95df0 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -25,6 +25,8 @@ #include "util/externalcommand.h" #include "util/report.h" +#include +#include #include #include #include @@ -46,7 +48,6 @@ ExternalCommand::ExternalCommand(CopySource& source, CopyTarget& target,const QP setup(processChannelMode); } - /** Starts copyBlocks command. */ bool ExternalCommand::startCopyBlocks() @@ -166,11 +167,13 @@ void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMod bool ExternalCommand::start(int timeout) { - this->moveToThread(CoreBackendManager::self()->kauthThread()); - QTimer::singleShot(0, this, &ExternalCommand::execute); - QEventLoop loop; - connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); - loop.exec(); +// this->moveToThread(CoreBackendManager::self()->kauthThread()); +// QTimer::singleShot(0, this, &ExternalCommand::execute); +// QEventLoop loop; +// connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); +// loop.exec(); +// return true; + execute(); return true; } @@ -186,35 +189,23 @@ void ExternalCommand::execute() if (cmd.isEmpty()) cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); - KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.start")); - action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); - arguments.insert(QStringLiteral("command"), cmd); - arguments.insert(QStringLiteral("input"), m_Input); - arguments.insert(QStringLiteral("arguments"), args()); - action.setArguments(arguments); - - KAuth::ExecuteJob *job = action.execute(); - if (!job->exec()) { - qWarning() << "KAuth returned an error code: " << job->errorString(); -// return false; - emit finished(); + if (!QDBusConnection::systemBus().isConnected()) { + qWarning() << "Could not connect to DBus session bus"; return; } - m_Output = job->data()[QStringLiteral("output")].toByteArray(); - setExitCode(job->data()[QStringLiteral("exitCode")].toInt()); + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + if (iface.isValid()) { + QDBusReply reply = iface.call(QStringLiteral("start"), CoreBackendManager::self()->Uuid(), cmd, args(), m_Input, QStringList()); + if (reply.isValid()) { + m_Output = reply.value()[QStringLiteral("output")].toByteArray(); + setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); + } + else { + qWarning() << reply.error().message(); + } + } -// QProcess::start(command(), args()); - - // FIXME -// if (!waitForStarted(timeout)) -// { -// if (report()) -// report()->line() << xi18nc("@info:status", "(Command timeout while starting)"); -// return false; -// } - -// return true; emit finished(); } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 00d4e0e..ae52a33 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -17,6 +17,8 @@ #include "externalcommandhelper.h" +#include +#include #include #include #include @@ -25,6 +27,30 @@ #include +/** Initialize ExternalCommandHelper Daemon and prepare DBus interface +*/ +ActionReply ExternalCommandHelper::init(const QVariantMap& args) +{ + ActionReply reply; + if (!QDBusConnection::systemBus().isConnected()) { + qWarning() << "Could not connect to DBus session bus"; + reply.addData(QStringLiteral("success"), false); + return reply; + } + m_callerUuid = args[QStringLiteral("callerUuid")].toString(); + + if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) { + qWarning() << QDBusConnection::systemBus().lastError().message(); + reply.addData(QStringLiteral("success"), false); + return reply; + } + QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); + + m_loop.exec(); + reply.addData(QStringLiteral("success"), true); + return reply; +} + /** Reads the given number of bytes from the sourceDevice into the given buffer. @param sourceDevice device or file to read from @param buffer buffer to store the bytes read in @@ -84,7 +110,7 @@ bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) { - command = args[QStringLiteral("command")].toString(); + m_command = args[QStringLiteral("command")].toString(); qint64 blockSize = args[QStringLiteral("blockSize")].toLongLong(); qint64 blocksToCopy = args[QStringLiteral("blocksToCopy")].toLongLong(); qint64 readOffset = args[QStringLiteral("readOffset")].toLongLong(); @@ -101,7 +127,7 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) ActionReply reply; - cmd.setEnvironment(environment); + m_cmd.setEnvironment(environment); qint64 bytesWritten = 0; qint64 blocksCopied = 0; @@ -171,28 +197,33 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) return reply; } -ActionReply ExternalCommandHelper::start(const QVariantMap& args) +QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) { - ActionReply reply; - QString command = args[QStringLiteral("command")].toString(); - QStringList arguments = args[QStringLiteral("arguments")].toStringList(); - QStringList environment = args[QStringLiteral("environment")].toStringList(); - QByteArray input = args[QStringLiteral("input")].toByteArray(); + QVariantMap reply; + if (Uuid != m_callerUuid) { + qWarning() << "Caller is not authorized"; + return reply; + } // connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); - cmd.setEnvironment(environment); - cmd.start(command, arguments); - cmd.write(input); - cmd.closeWriteChannel(); - cmd.waitForFinished(-1); - QByteArray output = cmd.readAllStandardOutput(); - reply.addData(QStringLiteral("output"), output); - reply.addData(QStringLiteral("exitCode"), cmd.exitCode()); + m_cmd.setEnvironment(environment); + m_cmd.start(command, arguments); + m_cmd.write(input); + m_cmd.closeWriteChannel(); + m_cmd.waitForFinished(-1); + QByteArray output = m_cmd.readAllStandardOutput(); + reply[QStringLiteral("output")] = output; + reply[QStringLiteral("exitCode")] = m_cmd.exitCode(); return reply; } +void ExternalCommandHelper::exit(const QString& Uuid) +{ + m_loop.exit(); +} + void ExternalCommandHelper::onReadOutput() { // const QByteArray s = cmd.readAllStandardOutput(); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index a7ff29b..0f05eec 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -16,11 +16,11 @@ *************************************************************************/ #ifndef KPMCORE_EXTERNALCOMMANDHELPER_H - #define KPMCORE_EXTERNALCOMMANDHELPER_H #include +#include #include #include @@ -29,24 +29,30 @@ using namespace KAuth; class ExternalCommandHelper : public QObject { Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.externalcommand") Q_SIGNALS: void progress(int); + void quit(); public: bool readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size); bool writeData(QString& targetDevice, QByteArray& buffer, qint64 offset); public Q_SLOTS: - ActionReply start(const QVariantMap& args); + ActionReply init(const QVariantMap& args); + Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); + Q_SCRIPTABLE void exit(const QString& Uuid); ActionReply copyblockshelper(const QVariantMap& args); private: void onReadOutput(); - QString command; - QString sourceDevice; - QProcess cmd; + QEventLoop m_loop; + QString m_callerUuid; + QString m_command; + QString m_sourceDevice; + QProcess m_cmd; // QByteArray output; }; diff --git a/src/util/org.kde.kpmcore.externalcommand.actions b/src/util/org.kde.kpmcore.externalcommand.actions index 4d935b2..0e69798 100644 --- a/src/util/org.kde.kpmcore.externalcommand.actions +++ b/src/util/org.kde.kpmcore.externalcommand.actions @@ -1,11 +1,5 @@ -[org.kde.kpmcore.externalcommand.start] -Name=Run external command action -Description=Run external command as privileged user -Policy=auth_admin -Persistence=session - -[org.kde.kpmcore.externalcommand.copyblockshelper] -Name=copy blocks external command action -Description=copy blocks external command as privileged user +[org.kde.kpmcore.externalcommand.init] +Name=Start external command daemon +Description=Root privileges are needed to manage disks Policy=auth_admin Persistence=session diff --git a/src/util/org.kde.kpmcore.helperinterface.conf b/src/util/org.kde.kpmcore.helperinterface.conf new file mode 100644 index 0000000..990dadf --- /dev/null +++ b/src/util/org.kde.kpmcore.helperinterface.conf @@ -0,0 +1,16 @@ + + + + + + + + + + + + + From ef2b61d2ecabe9eb8e73d87631f4ab325e0c8bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 19 Mar 2018 16:21:57 +0100 Subject: [PATCH 044/175] Wait until the helper started. Ideally we should not block at this stage and wait before the first command is executed. But this is much better than nothing. --- src/backend/corebackendmanager.cpp | 3 +++ src/util/externalcommandhelper.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index f52b4aa..bde70a6 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -74,6 +74,9 @@ void CoreBackendManager::startExternalCommandHelper() action.setArguments(arguments); KAuth::ExecuteJob *job = action.execute(); job->start(); + QEventLoop loop; + QObject::connect(job, &KAuth::ExecuteJob::newData, [&] () {loop.exit();}); + loop.exec(); } bool CoreBackendManager::load(const QString& name) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index ae52a33..ff3c72e 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -46,6 +46,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); + HelperSupport::progressStep(QVariantMap()); m_loop.exec(); reply.addData(QStringLiteral("success"), true); return reply; From bd54ba7c5d7a0d57feff6ac9f80919218a856bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 21 Mar 2018 18:01:40 +0100 Subject: [PATCH 045/175] Convert copyblocks code from KAuth to DBus calls to helper daemon. --- src/CMakeLists.txt | 2 +- src/backend/corebackendmanager.cpp | 13 ++++-- src/backend/corebackendmanager.h | 12 ++++- src/util/externalcommand.cpp | 71 +++++++++--------------------- src/util/externalcommandhelper.cpp | 51 +++++++++++---------- src/util/externalcommandhelper.h | 7 +-- test/CMakeLists.txt | 13 +++--- test/testdevicescanner.cpp | 2 + test/testinit.cpp | 3 ++ test/testlist.cpp | 3 ++ test/testsmart.cpp | 4 +- 11 files changed, 90 insertions(+), 91 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bf10203..2b6365a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,7 +39,7 @@ set(kpmcore_SRCS ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES}) add_library(kpmcore SHARED ${kpmcore_SRCS}) -target_link_libraries( kpmcore +target_link_libraries( kpmcore PUBLIC ${UUID_LIBRARIES} ${BLKID_LIBRARIES} Qt5::DBus diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index bde70a6..219a899 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -72,11 +72,18 @@ void CoreBackendManager::startExternalCommandHelper() m_Uuid = QUuid::createUuid().toString(); arguments.insert(QStringLiteral("callerUuid"), Uuid()); action.setArguments(arguments); - KAuth::ExecuteJob *job = action.execute(); - job->start(); + m_job = action.execute(); + job()->start(); QEventLoop loop; - QObject::connect(job, &KAuth::ExecuteJob::newData, [&] () {loop.exit();}); + auto exitLoop = [&] () {loop.exit();}; + auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); loop.exec(); + QObject::disconnect(conn); + +} + +KAuth::ExecuteJob* CoreBackendManager::job() { + return m_job; } bool CoreBackendManager::load(const QString& name) diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index d4f1351..ed04bd7 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -21,6 +21,8 @@ #include "util/libpartitionmanagerexport.h" +#include + #include #include @@ -93,12 +95,18 @@ public: return m_Uuid; } + /** + * @return a pointer to the KAuth job + */ + KAuth::ExecuteJob* job(); + private: void startExternalCommandHelper(); private: - CoreBackend* m_Backend; - QThread* m_KAuthThread; + CoreBackend *m_Backend; + QThread *m_KAuthThread; + KAuth::ExecuteJob *m_job; QString m_Uuid; }; diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index ba95df0..790eb05 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -63,62 +63,31 @@ bool ExternalCommand::startCopyBlocks() bool ExternalCommand::copyBlocks() { bool rval = true; - qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy - qint64 blocksToCopy = m_Source->length() / blockSize; + const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy - qint64 readOffset = m_Source->firstByte(); - qint64 writeOffset = m_Target->firstByte(); - qint32 copyDirection = 1; - - if (m_Target->firstByte() > m_Source->firstByte()) { - readOffset = m_Source->firstByte() + m_Source->length() - blockSize; - writeOffset = m_Target->firstByte() + m_Source->length() - blockSize; - copyDirection = -1; - } - qint64 lastBlock = m_Source->length() % blockSize; - - //report()->line() << xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy, m_source.length(), readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left") : i18nc("direction: right", "right")); - - QString cmd = QStandardPaths::findExecutable(QStringLiteral("dd")); - - if (cmd.isEmpty()) - cmd = QStandardPaths::findExecutable(QStringLiteral("dd"), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); - - KAuth::Action action(QStringLiteral("org.kde.kpmcore.externalcommand.copyblockshelper")); - action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); - - arguments.insert(QStringLiteral("command"), cmd); - arguments.insert(QStringLiteral("sourceDevice"), m_Source->path()); - arguments.insert(QStringLiteral("targetDevice"), m_Target->path()); - arguments.insert(QStringLiteral("blockSize"), blockSize); - arguments.insert(QStringLiteral("blocksToCopy"), blocksToCopy); - arguments.insert(QStringLiteral("readOffset"), readOffset); - arguments.insert(QStringLiteral("writeOffset"), writeOffset); - arguments.insert(QStringLiteral("copyDirection"), copyDirection); - arguments.insert(QStringLiteral("sourceFirstByte"), m_Source->firstByte()); - arguments.insert(QStringLiteral("targetFirstByte"), m_Target->firstByte()); - arguments.insert(QStringLiteral("lastBlock"), lastBlock); - arguments.insert(QStringLiteral("sourceLength"), m_Source->length()); - - action.setArguments(arguments); - action.setTimeout(24 * 3600 * 1000); // set 1 day DBus timeout - - KAuth::ExecuteJob *job = action.execute(); - // TODO KF6:Use new signal-slot syntax - connect(job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); - connect(job, &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); - - if (!job->exec()) { - qWarning() << "KAuth returned an error code: " << job->errorString(); -// return false; - emit finished(); + if (!QDBusConnection::systemBus().isConnected()) { + qWarning() << "Could not connect to DBus system bus"; return false; } - rval = job->data()[QStringLiteral("success")].toInt(); - setExitCode(!rval); + // TODO KF6:Use new signal-slot syntax + connect(CoreBackendManager::self()->job(), SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); + connect(CoreBackendManager::self()->job(), &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); + + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + if (iface.isValid()) { + QDBusReply reply = iface.call(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), m_Source->path(), m_Source->firstByte(), m_Source->length(), m_Target->path(), m_Target->firstByte(), blockSize); + if (reply.isValid()) { + rval = reply.value()[QStringLiteral("success")].toInt(); + qDebug() << rval; + } + else { + qWarning() << reply.error().message(); + } + } emit finished(); + setExitCode(!rval); return rval; } @@ -190,7 +159,7 @@ void ExternalCommand::execute() cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); if (!QDBusConnection::systemBus().isConnected()) { - qWarning() << "Could not connect to DBus session bus"; + qWarning() << "Could not connect to DBus system bus"; return; } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index ff3c72e..76cf992 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -59,7 +59,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) @param size the number of bytes to read @return true on success */ -bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size) +bool ExternalCommandHelper::readData(const QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size) { QFile device(sourceDevice); @@ -89,7 +89,7 @@ bool ExternalCommandHelper::readData(QString& sourceDevice, QByteArray& buffer, @param offset offset where to begin writing @return true on success */ -bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, qint64 offset) +bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteArray& buffer, qint64 offset) { QFile device(targetDevice); if (!device.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered)) { @@ -109,26 +109,23 @@ bool ExternalCommandHelper::writeData(QString &targetDevice, QByteArray& buffer, return true; } -ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) +QVariantMap ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { - m_command = args[QStringLiteral("command")].toString(); - qint64 blockSize = args[QStringLiteral("blockSize")].toLongLong(); - qint64 blocksToCopy = args[QStringLiteral("blocksToCopy")].toLongLong(); - qint64 readOffset = args[QStringLiteral("readOffset")].toLongLong(); - qint64 writeOffset = args[QStringLiteral("writeOffset")].toLongLong(); - qint32 copyDirection = args[QStringLiteral("copyDirection")].toLongLong(); - QString sourceDevice = args[QStringLiteral("sourceDevice")].toString(); - QString targetDevice = args[QStringLiteral("targetDevice")].toString(); - qint64 lastBlock = args[QStringLiteral("lastBlock")].toLongLong(); - qint64 sourceFirstByte = args[QStringLiteral("sourceFirstByte")].toLongLong(); - qint64 targetFirstByte = args[QStringLiteral("targetFirstByte")].toLongLong(); - qint64 sourceLength = args[QStringLiteral("sourceLength")].toLongLong(); + isCallerAuthorized(Uuid); + QVariantMap reply; - QStringList environment = args[QStringLiteral("environment")].toStringList(); + const qint64 blocksToCopy = sourceLength / blockSize; + qint64 readOffset = sourceFirstByte; + qint64 writeOffset = targetFirstByte; + qint32 copyDirection = 1; - ActionReply reply; + if (targetFirstByte > sourceFirstByte) { + readOffset = sourceFirstByte + sourceLength - blockSize; + writeOffset = targetFirstByte + sourceLength - blockSize; + copyDirection = -1; + } - m_cmd.setEnvironment(environment); + const qint64 lastBlock = sourceLength % blockSize; qint64 bytesWritten = 0; qint64 blocksCopied = 0; @@ -193,18 +190,15 @@ ActionReply ExternalCommandHelper::copyblockshelper(const QVariantMap& args) report[QStringLiteral("report")] = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten)); HelperSupport::progressStep(report); - reply.addData(QStringLiteral("success"), rval); + reply[QStringLiteral("success")] = rval; return reply; } QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) { + isCallerAuthorized(Uuid); QVariantMap reply; - if (Uuid != m_callerUuid) { - qWarning() << "Caller is not authorized"; - return reply; - } // connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); @@ -220,8 +214,19 @@ QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& com return reply; } +bool ExternalCommandHelper::isCallerAuthorized(const QString& Uuid) +{ + if (Uuid != m_callerUuid) { + qWarning() << "Caller is not authorized"; + return false; + } + + return true; +} + void ExternalCommandHelper::exit(const QString& Uuid) { + isCallerAuthorized(Uuid); m_loop.exit(); } diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 0f05eec..7714de3 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -36,17 +36,18 @@ Q_SIGNALS: void quit(); public: - bool readData(QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size); - bool writeData(QString& targetDevice, QByteArray& buffer, qint64 offset); + bool readData(const QString& sourceDevice, QByteArray& buffer, qint64 offset, qint64 size); + bool writeData(const QString& targetDevice, const QByteArray& buffer, qint64 offset); public Q_SLOTS: ActionReply init(const QVariantMap& args); Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); + Q_SCRIPTABLE QVariantMap copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); - ActionReply copyblockshelper(const QVariantMap& args); private: void onReadOutput(); + bool isCallerAuthorized(const QString& Uuid); QEventLoop m_loop; QString m_callerUuid; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 66681e1..25151b8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,11 +15,12 @@ add_compile_options(-fPIC) # Helper macro to link to the helper (for initialization of kpmcore) # and to add a test with the given name. # -add_library(testhelpers OBJECT helpers.cpp) +add_library(testhelpers STATIC helpers.cpp) +target_link_libraries(testhelpers KF5::Auth) macro (kpm_test name) - add_executable(${name} ${ARGN} $) - target_link_libraries(${name} kpmcore) + add_executable(${name} ${ARGN}) + target_link_libraries(${name} testhelpers kpmcore) endmacro() ### @@ -29,13 +30,13 @@ kpm_test(testinit testinit.cpp) # Default backend if(TARGET pmdummybackendplugin) add_test(NAME testinit-dummy COMMAND testinit $) endif() -if(TARGET pmlibpartedbackendplugin) - add_test(NAME testinit-parted COMMAND testinit $) +if(TARGET pmsfdiskbackendplugin) + add_test(NAME testinit-sfdisk COMMAND testinit $) else() return() # All the rest really needs a working backend endif() -set(BACKEND $) +set(BACKEND $) ### # diff --git a/test/testdevicescanner.cpp b/test/testdevicescanner.cpp index 88b2451..d3a39b6 100644 --- a/test/testdevicescanner.cpp +++ b/test/testdevicescanner.cpp @@ -30,6 +30,7 @@ #include "core/partition.h" #include "util/capacity.h" +#include #include #include @@ -63,6 +64,7 @@ PartitionList flatten(PartitionTable *table) int main( int argc, char **argv ) { + QCoreApplication app(argc, argv); if (argc != 2) { KPMCoreInitializer i; diff --git a/test/testinit.cpp b/test/testinit.cpp index 276c0f8..fd97f56 100644 --- a/test/testinit.cpp +++ b/test/testinit.cpp @@ -21,10 +21,13 @@ // the current platform, or if one is named on the command line, // loads that one. Returns 0 on success. +#include + #include "helpers.h" int main( int argc, char** argv ) { + QCoreApplication app(argc, argv); if ( argc != 2 ) { KPMCoreInitializer i; diff --git a/test/testlist.cpp b/test/testlist.cpp index 91ff06a..6b1c9eb 100644 --- a/test/testlist.cpp +++ b/test/testlist.cpp @@ -27,6 +27,7 @@ #include "core/partition.h" #include "util/capacity.h" +#include #include #include @@ -60,6 +61,8 @@ PartitionList flatten(PartitionTable *table) int main( int argc, char **argv ) { + QCoreApplication app(argc, argv); + if (argc != 2) { KPMCoreInitializer i; diff --git a/test/testsmart.cpp b/test/testsmart.cpp index ea5aa72..ad8c098 100644 --- a/test/testsmart.cpp +++ b/test/testsmart.cpp @@ -6,7 +6,7 @@ #include "core/smartstatus.h" #include "core/smartparser.h" -#include +#include #include static QString getDefaultDevicePath(); @@ -15,7 +15,7 @@ static bool testSmartParser(); int main(int argc, char **argv) { - QApplication app(argc, argv); + QCoreApplication app(argc, argv); KPMCoreInitializer i; From c09f6fb9fa68e5c266bc4d2af2be871423c5e764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 21 Mar 2018 20:44:07 +0100 Subject: [PATCH 046/175] Add a function to stop KAuth helper daemon. --- src/backend/corebackendmanager.cpp | 6 ++++++ src/backend/corebackendmanager.h | 5 +++++ test/helpers.cpp | 5 +++++ test/helpers.h | 1 + 4 files changed, 17 insertions(+) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 219a899..195bbf6 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -79,7 +79,13 @@ void CoreBackendManager::startExternalCommandHelper() auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); loop.exec(); QObject::disconnect(conn); +} +void CoreBackendManager::stopExternalCommandHelper() +{ + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + if (iface.isValid()) + iface.call(QStringLiteral("exit"), CoreBackendManager::self()->Uuid()); } KAuth::ExecuteJob* CoreBackendManager::job() { diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index ed04bd7..d6b843a 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -100,6 +100,11 @@ public: */ KAuth::ExecuteJob* job(); + /** + * stop ExternalCommand Helper + */ + static void stopExternalCommandHelper(); + private: void startExternalCommandHelper(); diff --git a/test/helpers.cpp b/test/helpers.cpp index de1b73f..e562fce 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -56,3 +56,8 @@ KPMCoreInitializer::KPMCoreInitializer( const QString& backendName ) : KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializer( QString::fromLatin1( backend ) ) { } + +KPMCoreInitializer::~KPMCoreInitializer() +{ + CoreBackendManager::stopExternalCommandHelper(); +} diff --git a/test/helpers.h b/test/helpers.h index 0900418..eae46b0 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -32,6 +32,7 @@ public: KPMCoreInitializer(); /// Default backend KPMCoreInitializer( const QString& backend ); /// Use named backend KPMCoreInitializer( const char* backend ); /// Use named backend + ~KPMCoreInitializer(); bool isValid() const { From 97d70764810655c48d3e7abcefddc7dff062eadf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 21 Mar 2018 21:11:09 +0100 Subject: [PATCH 047/175] Increase DBus call timeout to 10 days. --- src/util/externalcommand.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 790eb05..100ad72 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -75,11 +75,11 @@ bool ExternalCommand::copyBlocks() connect(CoreBackendManager::self()->job(), &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { QDBusReply reply = iface.call(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), m_Source->path(), m_Source->firstByte(), m_Source->length(), m_Target->path(), m_Target->firstByte(), blockSize); if (reply.isValid()) { rval = reply.value()[QStringLiteral("success")].toInt(); - qDebug() << rval; } else { qWarning() << reply.error().message(); @@ -164,6 +164,7 @@ void ExternalCommand::execute() } QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { QDBusReply reply = iface.call(QStringLiteral("start"), CoreBackendManager::self()->Uuid(), cmd, args(), m_Input, QStringList()); if (reply.isValid()) { From 4b91f2c07eced1fbd7bbc3cf3b0e0afb38959de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 21 Mar 2018 21:51:30 +0100 Subject: [PATCH 048/175] Convert copyblocks dbus call to asynchronous call. --- src/util/externalcommand.cpp | 28 +++++++++++++++++++--------- src/util/externalcommandhelper.cpp | 7 ++----- src/util/externalcommandhelper.h | 2 +- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 100ad72..1400cfb 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -77,17 +77,27 @@ bool ExternalCommand::copyBlocks() QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { - QDBusReply reply = iface.call(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), m_Source->path(), m_Source->firstByte(), m_Source->length(), m_Target->path(), m_Target->firstByte(), blockSize); - if (reply.isValid()) { - rval = reply.value()[QStringLiteral("success")].toInt(); - } - else { - qWarning() << reply.error().message(); - } + QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), m_Source->path(), m_Source->firstByte(), m_Source->length(), m_Target->path(), m_Target->firstByte(), blockSize); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + QEventLoop loop; + + auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { + loop.exit(); + if (watcher->isError()) { + qWarning() << watcher->error(); + } + else { + QDBusPendingReply reply = *watcher; + rval = reply.argumentAt<0>(); + } + emit finished(); + setExitCode(!rval); + }; + + connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); + loop.exec(); } - emit finished(); - setExitCode(!rval); return rval; } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 76cf992..159af88 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -109,10 +109,9 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr return true; } -QVariantMap ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) +bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { isCallerAuthorized(Uuid); - QVariantMap reply; const qint64 blocksToCopy = sourceLength / blockSize; qint64 readOffset = sourceFirstByte; @@ -190,9 +189,7 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& Uuid, const QString report[QStringLiteral("report")] = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten)); HelperSupport::progressStep(report); - reply[QStringLiteral("success")] = rval; - - return reply; + return rval; } QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 7714de3..caf0935 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -42,7 +42,7 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); - Q_SCRIPTABLE QVariantMap copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); + Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); private: From dac3372a78c9a36acd058554f0111341362ed404 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Thu, 22 Mar 2018 02:32:59 -0300 Subject: [PATCH 049/175] - Including ExternalCommandHelper asynchronous DBus call in ExternalCommand::execute - Stop helper before starting a new in CoreBackendManager::startExternalCommandHelper - Unregister org.kde.kpmcore.helperinterface service in ExternalCommandHelper::exit --- src/backend/corebackendmanager.cpp | 2 ++ src/util/externalcommand.cpp | 52 ++++++++++++++++++++++-------- src/util/externalcommandhelper.cpp | 5 +++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 195bbf6..3f9b817 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -65,6 +65,8 @@ QVector CoreBackendManager::list() const void CoreBackendManager::startExternalCommandHelper() { + stopExternalCommandHelper(); + KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 1400cfb..c77ad36 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -152,6 +152,7 @@ bool ExternalCommand::start(int timeout) // connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); // loop.exec(); // return true; + Q_UNUSED(timeout) execute(); return true; } @@ -173,20 +174,43 @@ void ExternalCommand::execute() return; } - QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); - iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days - if (iface.isValid()) { - QDBusReply reply = iface.call(QStringLiteral("start"), CoreBackendManager::self()->Uuid(), cmd, args(), m_Input, QStringList()); - if (reply.isValid()) { - m_Output = reply.value()[QStringLiteral("output")].toByteArray(); - setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); - } - else { - qWarning() << reply.error().message(); - } - } + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), + QStringLiteral("/Helper"), + QStringLiteral("org.kde.kpmcore.externalcommand"), + QDBusConnection::systemBus()); - emit finished(); + iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days + + if (iface.isValid()) { + QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), + CoreBackendManager::self()->Uuid(), + cmd, + args(), + m_Input, + QStringList()); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + + QEventLoop loop; + + auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { + loop.exit(); + + if (watcher->isError()) + qWarning() << watcher->error(); + else { + QDBusPendingReply reply = *watcher; + + m_Output = reply.value()[QStringLiteral("output")].toByteArray(); + setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); + } + + emit finished(); + }; + + connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); + loop.exec(); + } } bool ExternalCommand::write(const QByteArray& input) @@ -210,7 +234,7 @@ bool ExternalCommand::waitFor(int timeout) }*/ // onReadOutput(); - + Q_UNUSED(timeout) return true; } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 159af88..a4d9012 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -225,6 +225,11 @@ void ExternalCommandHelper::exit(const QString& Uuid) { isCallerAuthorized(Uuid); m_loop.exit(); + + if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"))) + qDebug() << "org.kde.kpmcore.helperinterface unregistered"; + + QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper")); } void ExternalCommandHelper::onReadOutput() From 39d3592c23d443b0c6c2375831cb8a513a61fa31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 22 Mar 2018 17:41:49 +0100 Subject: [PATCH 050/175] Actually check if the caller is authorized. --- src/backend/corebackendmanager.cpp | 2 -- src/util/externalcommand.cpp | 21 +++++---------------- src/util/externalcommand.h | 2 -- src/util/externalcommandhelper.cpp | 13 +++++++++---- 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 3f9b817..195bbf6 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -65,8 +65,6 @@ QVector CoreBackendManager::list() const void CoreBackendManager::startExternalCommandHelper() { - stopExternalCommandHelper(); - KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index c77ad36..533cde1 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -139,28 +139,14 @@ void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMod // connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); } -/** Starts the external command. +/** Executes the external command. @param timeout timeout to wait for the process to start @return true on success */ - bool ExternalCommand::start(int timeout) { -// this->moveToThread(CoreBackendManager::self()->kauthThread()); -// QTimer::singleShot(0, this, &ExternalCommand::execute); -// QEventLoop loop; -// connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); -// loop.exec(); -// return true; Q_UNUSED(timeout) - execute(); - return true; -} -/** Executes the external command in kauthThread() thread. -*/ -void ExternalCommand::execute() -{ if (report()) { report()->setCommand(xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" ")))); } @@ -171,7 +157,7 @@ void ExternalCommand::execute() if (!QDBusConnection::systemBus().isConnected()) { qWarning() << "Could not connect to DBus system bus"; - return; + return false; } QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), @@ -181,6 +167,7 @@ void ExternalCommand::execute() iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days + bool rval = false; if (iface.isValid()) { QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), CoreBackendManager::self()->Uuid(), @@ -206,11 +193,13 @@ void ExternalCommand::execute() } emit finished(); + rval = true; }; connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); loop.exec(); } + return rval; } bool ExternalCommand::write(const QByteArray& input) diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 3acace8..01b02bf 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -93,8 +93,6 @@ public Q_SLOTS: void emitProgress(KJob*, unsigned long percent) { emit progress(percent); }; protected: - void execute(); - void setExitCode(int i) { m_ExitCode = i; } diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index a4d9012..6b0ebaa 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2017 by Andrius Štikonas * + * Copyright (C) 2017-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -111,7 +111,8 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { - isCallerAuthorized(Uuid); + if (!isCallerAuthorized(Uuid)) + return false; const qint64 blocksToCopy = sourceLength / blockSize; qint64 readOffset = sourceFirstByte; @@ -194,8 +195,11 @@ bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourc QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) { - isCallerAuthorized(Uuid); QVariantMap reply; + if (!isCallerAuthorized(Uuid)) { + reply[QStringLiteral("success")] = false; + return reply; + } // connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); @@ -223,7 +227,8 @@ bool ExternalCommandHelper::isCallerAuthorized(const QString& Uuid) void ExternalCommandHelper::exit(const QString& Uuid) { - isCallerAuthorized(Uuid); + if (!isCallerAuthorized(Uuid)) + return; m_loop.exit(); if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"))) From 2cef3f6ec6f18ebb24f99edc3940521a75e5e640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 22 Mar 2018 17:29:40 +0000 Subject: [PATCH 051/175] Cleanup ExternalCommand interface: * Remove a separate constructor for copyblocks. * Remove kauthThread and finished() signal. --- src/backend/corebackendmanager.cpp | 5 +---- src/backend/corebackendmanager.h | 10 +-------- src/jobs/checkfilesystemjob.cpp | 1 - src/jobs/job.cpp | 6 +++--- src/util/externalcommand.cpp | 33 +++++------------------------- src/util/externalcommand.h | 7 ++----- src/util/externalcommandhelper.h | 2 +- 7 files changed, 13 insertions(+), 51 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 195bbf6..04cc7b2 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -1,7 +1,7 @@ /************************************************************************* * Copyright (C) 2010 by Volker Lanz * * Copyright (C) 2015 by Teo Mrnjavac * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -38,8 +37,6 @@ CoreBackendManager::CoreBackendManager() : m_Backend(nullptr) { - m_KAuthThread = new QThread(); - kauthThread()->start(); } CoreBackendManager* CoreBackendManager::self() diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index d6b843a..a754252 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2010 by Volker Lanz * + * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -26,7 +27,6 @@ #include #include -class QThread; class QString; class QStringList; class KPluginMetaData; @@ -81,13 +81,6 @@ public: return m_Backend; } - /** - * @return a pointer to the thread where ExternalCommand will start KAuth job - */ - QThread* kauthThread() { - return m_KAuthThread; - } - /** * @return a pointer to the currently loaded backend */ @@ -110,7 +103,6 @@ private: private: CoreBackend *m_Backend; - QThread *m_KAuthThread; KAuth::ExecuteJob *m_job; QString m_Uuid; diff --git a/src/jobs/checkfilesystemjob.cpp b/src/jobs/checkfilesystemjob.cpp index 55110f2..7b7cd92 100644 --- a/src/jobs/checkfilesystemjob.cpp +++ b/src/jobs/checkfilesystemjob.cpp @@ -25,7 +25,6 @@ #include "util/report.h" #include -#include #include diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index 453521b..8ba23ae 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008, 2009, 2010 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -42,10 +42,10 @@ Job::Job() : bool Job::copyBlocks(Report& report, CopyTarget& target, CopySource& source) { m_Report = &report; - ExternalCommand copyCmd(source, target, QProcess::SeparateChannels); + ExternalCommand copyCmd; connect(©Cmd, &ExternalCommand::progress, this, &Job::progress, Qt::QueuedConnection); connect(©Cmd, &ExternalCommand::reportSignal, this, &Job::updateReport, Qt::QueuedConnection); - if (copyCmd.startCopyBlocks() && copyCmd.exitCode() == 0) { + if (copyCmd.copyBlocks(source, target)) { return true; } diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 533cde1..8cfe5b3 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -39,28 +39,7 @@ #include #include - -ExternalCommand::ExternalCommand(CopySource& source, CopyTarget& target,const QProcess::ProcessChannelMode processChannelMode) : - m_ExitCode(-1), - m_Source(&source), - m_Target(&target) -{ - setup(processChannelMode); -} - -/** Starts copyBlocks command. -*/ -bool ExternalCommand::startCopyBlocks() -{ - this->moveToThread(CoreBackendManager::self()->kauthThread()); - QTimer::singleShot(0, this, &ExternalCommand::copyBlocks); - QEventLoop loop; - connect(this, &ExternalCommand::finished, &loop, &QEventLoop::quit); - loop.exec(); - return true; -} - -bool ExternalCommand::copyBlocks() +bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) { bool rval = true; const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy @@ -77,7 +56,7 @@ bool ExternalCommand::copyBlocks() QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { - QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), m_Source->path(), m_Source->firstByte(), m_Source->length(), m_Target->path(), m_Target->firstByte(), blockSize); + QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); QEventLoop loop; @@ -90,7 +69,6 @@ bool ExternalCommand::copyBlocks() QDBusPendingReply reply = *watcher; rval = reply.argumentAt<0>(); } - emit finished(); setExitCode(!rval); }; @@ -190,15 +168,14 @@ bool ExternalCommand::start(int timeout) m_Output = reply.value()[QStringLiteral("output")].toByteArray(); setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); + rval = true; } - - emit finished(); - rval = true; }; connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); loop.exec(); } + return rval; } diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 01b02bf..cf9e41e 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -49,10 +50,9 @@ class LIBKPMCORE_EXPORT ExternalCommand : public QObject public: explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); - explicit ExternalCommand(CopySource& source, CopyTarget& target, QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); public: - bool copyBlocks(); + bool copyBlocks(CopySource& source, CopyTarget& target); void setCommand(const QString& cmd) { m_Command = cmd; } /**< @param cmd the command to run */ const QString& command() const { return m_Command; } /**< @return the command to run */ @@ -86,7 +86,6 @@ public: Q_SIGNALS: void progress(int); - void finished(); void reportSignal(const QVariantMap&); public Q_SLOTS: @@ -110,8 +109,6 @@ private: int m_ExitCode; QByteArray m_Output; QByteArray m_Input; - CopySource *m_Source; - CopyTarget *m_Target; }; #endif diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index caf0935..0a7590f 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2017 by Andrius Štikonas * + * Copyright (C) 2017-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * From ca136dfcaaa83648d59a6f04bb86dec6d143e86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 22 Mar 2018 17:52:59 +0000 Subject: [PATCH 052/175] Add some comments. Move copyblocks function lower in a file. --- src/backend/corebackendmanager.cpp | 2 + src/util/externalcommand.cpp | 86 ++++++++++++++++-------------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 04cc7b2..5b6c00c 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -71,6 +71,8 @@ void CoreBackendManager::startExternalCommandHelper() action.setArguments(arguments); m_job = action.execute(); job()->start(); + + // Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop) QEventLoop loop; auto exitLoop = [&] () {loop.exit();}; auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 8cfe5b3..9f7cd74 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -39,46 +39,6 @@ #include #include -bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) -{ - bool rval = true; - const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy - - if (!QDBusConnection::systemBus().isConnected()) { - qWarning() << "Could not connect to DBus system bus"; - return false; - } - - // TODO KF6:Use new signal-slot syntax - connect(CoreBackendManager::self()->job(), SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); - connect(CoreBackendManager::self()->job(), &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); - - QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); - iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days - if (iface.isValid()) { - QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), CoreBackendManager::self()->Uuid(), source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); - QEventLoop loop; - - auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { - loop.exit(); - if (watcher->isError()) { - qWarning() << watcher->error(); - } - else { - QDBusPendingReply reply = *watcher; - rval = reply.argumentAt<0>(); - } - setExitCode(!rval); - }; - - connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); - loop.exec(); - } - - return rval; -} - /** Creates a new ExternalCommand instance without Report. @param cmd the command to run @param args the arguments to pass to the command @@ -179,6 +139,52 @@ bool ExternalCommand::start(int timeout) return rval; } +bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) +{ + bool rval = true; + const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy + + if (!QDBusConnection::systemBus().isConnected()) { + qWarning() << "Could not connect to DBus system bus"; + return false; + } + + // TODO KF6:Use new signal-slot syntax + connect(CoreBackendManager::self()->job(), SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); + connect(CoreBackendManager::self()->job(), &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); + + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days + if (iface.isValid()) { + // Use asynchronous DBus calls, so that we can process reports and progress + QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), + CoreBackendManager::self()->Uuid(), + source.path(), source.firstByte(), source.length(), + target.path(), target.firstByte(), blockSize); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + QEventLoop loop; + + auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { + loop.exit(); + if (watcher->isError()) { + qWarning() << watcher->error(); + } + else { + QDBusPendingReply reply = *watcher; + rval = reply.argumentAt<0>(); + } + setExitCode(!rval); + }; + + connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); + loop.exec(); + } + + return rval; +} + + bool ExternalCommand::write(const QByteArray& input) { m_Input = input; From 47a1519699a59765fcdfa05b0d830401c8016fb3 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 23 Mar 2018 18:19:33 -0300 Subject: [PATCH 053/175] - Including Watchdog Timer in CoreBackendManager to ping DBus service. - Including ExternalCommandHelper::ping slot to receive pings. - Including timer to watch last ping in the service to unregister it after reaching 42 seconds without pings. --- src/backend/corebackendmanager.cpp | 17 ++++++++++++++++ src/util/externalcommandhelper.cpp | 31 ++++++++++++++++++++++++++++++ src/util/externalcommandhelper.h | 7 +++++++ 3 files changed, 55 insertions(+) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 5b6c00c..aaea5d4 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,22 @@ void CoreBackendManager::startExternalCommandHelper() auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); loop.exec(); QObject::disconnect(conn); + + // Watchdog Timer for the DBus service + QTimer *timer = new QTimer; + + auto sendDBusPing = [&] () { + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), + QStringLiteral("/Helper"), + QStringLiteral("org.kde.kpmcore.externalcommand"), + QDBusConnection::systemBus()); + + if (iface.isValid()) + iface.call(QStringLiteral("ping"), CoreBackendManager::self()->Uuid()); + }; + + QObject::connect(timer, &QTimer::timeout, sendDBusPing); + timer->start(20000); // 20 seconds } void CoreBackendManager::stopExternalCommandHelper() diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 6b0ebaa..5eef104 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -17,6 +17,7 @@ #include "externalcommandhelper.h" +#include #include #include #include @@ -49,6 +50,13 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) HelperSupport::progressStep(QVariantMap()); m_loop.exec(); reply.addData(QStringLiteral("success"), true); + + m_pingTime = new QDateTime(QDateTime::currentDateTime()); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &ExternalCommandHelper::checkPing); + timer->start(20000); // check ping every 20 secs + return reply; } @@ -237,6 +245,29 @@ void ExternalCommandHelper::exit(const QString& Uuid) QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper")); } +void ExternalCommandHelper::ping(const QString &Uuid) +{ + if (!isCallerAuthorized(Uuid)) + return; + + // update ping + m_pingTime->setDate(QDate::currentDate()); + m_pingTime->setTime(QTime::currentTime()); +} + +void ExternalCommandHelper::checkPing() +{ + qint64 mSecsSinceLastPing = m_pingTime->msecsTo(QDateTime::currentDateTime()); + + qDebug() << (((double)mSecsSinceLastPing) / 1000) << " seconds since the last ping."; + + if (mSecsSinceLastPing >= 42000) { // more than 42 seconds since the last ping + qDebug() << "Ending DBus service"; + + exit(m_callerUuid); + } +} + void ExternalCommandHelper::onReadOutput() { // const QByteArray s = cmd.readAllStandardOutput(); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 0a7590f..4aea8d4 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -44,6 +45,10 @@ public Q_SLOTS: Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); + Q_SCRIPTABLE void ping(const QString& Uuid); + +private Q_SLOTS: + void checkPing(); private: void onReadOutput(); @@ -54,6 +59,8 @@ private: QString m_command; QString m_sourceDevice; QProcess m_cmd; + + QDateTime *m_pingTime; // QByteArray output; }; From 8cdf70171ea2d2a1cb9bb551e952fbc12b7398f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 23 Mar 2018 22:08:23 +0000 Subject: [PATCH 054/175] Start QTimer before enteting event loop. --- src/util/externalcommandhelper.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 5eef104..a877dd7 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -47,16 +47,16 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); - HelperSupport::progressStep(QVariantMap()); - m_loop.exec(); - reply.addData(QStringLiteral("success"), true); - m_pingTime = new QDateTime(QDateTime::currentDateTime()); QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &ExternalCommandHelper::checkPing); timer->start(20000); // check ping every 20 secs + HelperSupport::progressStep(QVariantMap()); + m_loop.exec(); + reply.addData(QStringLiteral("success"), true); + return reply; } @@ -259,11 +259,9 @@ void ExternalCommandHelper::checkPing() { qint64 mSecsSinceLastPing = m_pingTime->msecsTo(QDateTime::currentDateTime()); - qDebug() << (((double)mSecsSinceLastPing) / 1000) << " seconds since the last ping."; + qDebug() << mSecsSinceLastPing / 1000.0 << " seconds since the last ping."; if (mSecsSinceLastPing >= 42000) { // more than 42 seconds since the last ping - qDebug() << "Ending DBus service"; - exit(m_callerUuid); } } From f04416beba14e2d41e909946cb261cd1e6c59c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 23 Mar 2018 22:45:51 +0000 Subject: [PATCH 055/175] Simplify Qtimer code in ExternalCommandHelper. --- src/util/externalcommandhelper.cpp | 28 +++++++--------------------- src/util/externalcommandhelper.h | 8 +++----- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index a877dd7..4591307 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -17,9 +17,7 @@ #include "externalcommandhelper.h" -#include #include -#include #include #include #include @@ -28,6 +26,9 @@ #include +// exit helper if no ping for 42s +#define TIMEOUT 42000 + /** Initialize ExternalCommandHelper Daemon and prepare DBus interface */ ActionReply ExternalCommandHelper::init(const QVariantMap& args) @@ -47,11 +48,9 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); - m_pingTime = new QDateTime(QDateTime::currentDateTime()); - - QTimer *timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, &ExternalCommandHelper::checkPing); - timer->start(20000); // check ping every 20 secs + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, [=] () { exit(m_callerUuid); }); + timer->start(TIMEOUT); HelperSupport::progressStep(QVariantMap()); m_loop.exec(); @@ -250,20 +249,7 @@ void ExternalCommandHelper::ping(const QString &Uuid) if (!isCallerAuthorized(Uuid)) return; - // update ping - m_pingTime->setDate(QDate::currentDate()); - m_pingTime->setTime(QTime::currentTime()); -} - -void ExternalCommandHelper::checkPing() -{ - qint64 mSecsSinceLastPing = m_pingTime->msecsTo(QDateTime::currentDateTime()); - - qDebug() << mSecsSinceLastPing / 1000.0 << " seconds since the last ping."; - - if (mSecsSinceLastPing >= 42000) { // more than 42 seconds since the last ping - exit(m_callerUuid); - } + timer->setInterval(TIMEOUT); } void ExternalCommandHelper::onReadOutput() diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 4aea8d4..aba456a 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -20,11 +20,12 @@ #include -#include #include #include #include +class QTimer; + using namespace KAuth; class ExternalCommandHelper : public QObject @@ -47,9 +48,6 @@ public Q_SLOTS: Q_SCRIPTABLE void exit(const QString& Uuid); Q_SCRIPTABLE void ping(const QString& Uuid); -private Q_SLOTS: - void checkPing(); - private: void onReadOutput(); bool isCallerAuthorized(const QString& Uuid); @@ -60,7 +58,7 @@ private: QString m_sourceDevice; QProcess m_cmd; - QDateTime *m_pingTime; + QTimer *timer; // QByteArray output; }; From a4be3fd2eaba79474ee3bac439a60489c457a9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 24 Mar 2018 15:32:15 +0000 Subject: [PATCH 056/175] Start KAuth helper in CoreBackendManager constructor. --- src/backend/corebackendmanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index aaea5d4..f2ab2b7 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -38,6 +38,7 @@ CoreBackendManager::CoreBackendManager() : m_Backend(nullptr) { + startExternalCommandHelper(); } CoreBackendManager* CoreBackendManager::self() @@ -131,8 +132,6 @@ bool CoreBackendManager::load(const QString& name) backend()->setVersion(version); qDebug() << "Loaded backend plugin: " << backend()->id(); - startExternalCommandHelper(); - return true; } From f8f25dc82ae13bb31fc63cc9e392a6af8bf0e8a9 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sat, 24 Mar 2018 15:17:30 -0300 Subject: [PATCH 057/175] - Changing SmartQuirkDatabase to store QString instead of char*. - Changing quirkDatabase function to return QVector instead of SmartQuirkDatabase*. --- src/core/smartattributeparseddata.cpp | 309 ++++++++++++-------------- src/core/smartattributeparseddata.h | 13 +- 2 files changed, 158 insertions(+), 164 deletions(-) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index 3de8344..d3e832f 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL)) #define MKELVIN_VALID_MAX ((qint64) ((100LL*1000LL) + 273150LL)) @@ -477,187 +478,171 @@ static const QMap tableUni return table; } -static const SmartAttributeParsedData::SmartQuirkDataBase *quirkDatabase() +static const QVector quirkDatabase() { - static const SmartAttributeParsedData::SmartQuirkDataBase quirkDb[] = { - { - "^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$", - "^0085000B$", - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_197_UNKNOWN | - SmartAttributeParsedData::SMART_QUIRK_198_UNKNOWN) - }, - { - "^FUJITSU MHR2040AT$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | - SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | - SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT) - }, - { - "^FUJITSU MHS20[6432]0AT( .)?$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | - SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | - SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT | - SmartAttributeParsedData::SMART_QUIRK_201_DETECTEDTACOUNT) - }, - { - "^(" - "FUJITSU M1623TAU|" - "FUJITSU MHG2...ATU?.*|" - "FUJITSU MHH2...ATU?.*|" - "FUJITSU MHJ2...ATU?.*|" - "FUJITSU MHK2...ATU?.*|" - "FUJITSU MHL2300AT|" - "FUJITSU MHM2(20|15|10|06)0AT|" - "FUJITSU MHN2...AT|" - "FUJITSU MHR2020AT|" - "FUJITSU MHT2...(AH|AS|AT|BH)U?.*|" - "FUJITSU MHU2...ATU?.*|" - "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*|" - "FUJITSU MP[A-G]3...A[HTEV]U?.*" - ")$", - NULL, - SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS - }, - { - "^(" - "SAMSUNG SV4012H|" - "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]" - ")$", - NULL, - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES - }, - { - "^(" - "SAMSUNG SV0412H|" - "SAMSUNG SV1204H" - ")$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES | - SmartAttributeParsedData::SMART_QUIRK_194_10XCELSIUS) - }, - { - "^SAMSUNG SP40A2H$", - "^RR100-07$", - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES - }, - { - "^SAMSUNG SP80A4H$", - "^RT100-06$", - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES - }, - { - "^SAMSUNG SP8004H$", - "^QW100-61$", - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES - }, - { - "^(" - "Maxtor 2B0(0[468]|1[05]|20)H1|" - "Maxtor 4G(120J6|160J[68])|" - "Maxtor 4D0(20H1|40H2|60H3|80H4)" - ")$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_194_UNKNOWN) - }, - { - "^(" - "Maxtor 2F0[234]0[JL]0|" - "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|" - "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)|" - "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)|" - "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)|" - "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)|" - "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)|" - "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)|" - "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)|" - "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)|" - "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)|" - "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)|" - "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)|" - "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)|" - "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)|" - "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?|" - "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)|" - "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)|" - "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)|" - "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)|" - "Maxtor (98196H8|96147H6)|" - "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)|" - "Maxtor 6(E0[234]|K04)0L0|" - "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0|" - "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)|" - "Maxtor 7Y250[PM]0|" - "Maxtor [45]A(25|30|32)0[JN]0|" - "Maxtor 7L(25|30)0[SR]0" - ")$", - NULL, - SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES - }, - { - "^(" - "HITACHI_DK14FA-20B|" - "HITACHI_DK23..-..B?|" - "HITACHI_DK23FA-20J|HTA422020F9AT[JN]0|" - "HE[JN]4230[23]0F9AT00|" - "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00" - ")$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_193_LOADUNLOAD) - }, - { - "^HTS541010G9SA00$", - "^MBZOC60P$", - SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN - }, - { - "^MCCOE64GEMPP$", - "^2.9.0[3-9]$", - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN | - SmartAttributeParsedData::SMART_QUIRK_190_UNKNOWN) - }, - { - "^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$", - NULL, - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_3_UNUSED | - SmartAttributeParsedData::SMART_QUIRK_4_UNUSED | - SmartAttributeParsedData::SMART_QUIRK_225_TOTALLBASWRITTEN | - SmartAttributeParsedData::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR | - SmartAttributeParsedData::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS | - SmartAttributeParsedData::SMART_QUIRK_228_WORKLOADTIMER | - SmartAttributeParsedData::SMART_QUIRK_232_AVAILABLERESERVEDSPACE | - SmartAttributeParsedData::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) - } - }; + typedef SmartAttributeParsedData::SmartQuirkDataBase QuirkDatabase; + + QVector quirkDb; + + quirkDb << QuirkDatabase(QStringLiteral("^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$"), QStringLiteral("^0085000B$"), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_197_UNKNOWN | + SmartAttributeParsedData::SMART_QUIRK_198_UNKNOWN)); + + quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHR2040AT$"), QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | + SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT)); + + quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHS20[6432]0AT( .)?$"), QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | + SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT | + SmartAttributeParsedData::SMART_QUIRK_201_DETECTEDTACOUNT)); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "FUJITSU M1623TAU|" + "FUJITSU MHG2...ATU?.*|" + "FUJITSU MHH2...ATU?.*|" + "FUJITSU MHJ2...ATU?.*|" + "FUJITSU MHK2...ATU?.*|" + "FUJITSU MHL2300AT|" + "FUJITSU MHM2(20|15|10|06)0AT|" + "FUJITSU MHN2...AT|" + "FUJITSU MHR2020AT|" + "FUJITSU MHT2...(AH|AS|AT|BH)U?.*|" + "FUJITSU MHU2...ATU?.*|" + "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*|" + "FUJITSU MP[A-G]3...A[HTEV]U?.*" + ")$"), + QStringLiteral(), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "SAMSUNG SV4012H|" + "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]" + ")$"), + QStringLiteral(), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "SAMSUNG SV0412H|" + "SAMSUNG SV1204H" + ")$"), + QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES | + SmartAttributeParsedData::SMART_QUIRK_194_10XCELSIUS)); + + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP40A2H$"), + QStringLiteral("^RR100-07$"), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP80A4H$"), + QStringLiteral("^RT100-06$"), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP8004H$"), + QStringLiteral("^QW100-61$"), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "Maxtor 2B0(0[468]|1[05]|20)H1|" + "Maxtor 4G(120J6|160J[68])|" + "Maxtor 4D0(20H1|40H2|60H3|80H4)" + ")$"), + QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_194_UNKNOWN)); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "Maxtor 2F0[234]0[JL]0|" + "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|" + "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)|" + "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)|" + "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)|" + "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)|" + "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)|" + "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)|" + "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)|" + "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)|" + "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)|" + "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)|" + "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)|" + "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)|" + "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)|" + "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?|" + "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)|" + "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)|" + "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)|" + "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)|" + "Maxtor (98196H8|96147H6)|" + "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)|" + "Maxtor 6(E0[234]|K04)0L0|" + "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0|" + "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)|" + "Maxtor 7Y250[PM]0|" + "Maxtor [45]A(25|30|32)0[JN]0|" + "Maxtor 7L(25|30)0[SR]0" + ")$"), + QStringLiteral(), + SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES); + + quirkDb << QuirkDatabase(QStringLiteral("^(" + "HITACHI_DK14FA-20B|" + "HITACHI_DK23..-..B?|" + "HITACHI_DK23FA-20J|HTA422020F9AT[JN]0|" + "HE[JN]4230[23]0F9AT00|" + "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00" + ")$"), + QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | + SmartAttributeParsedData::SMART_QUIRK_193_LOADUNLOAD)); + + quirkDb << QuirkDatabase(QStringLiteral("^HTS541010G9SA00$"), + QStringLiteral("^MBZOC60P$"), + SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN); + + quirkDb << QuirkDatabase(QStringLiteral("^MCCOE64GEMPP$"), + QStringLiteral("^2.9.0[3-9]$"), + (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN | + SmartAttributeParsedData::SMART_QUIRK_190_UNKNOWN)); + + quirkDb << QuirkDatabase(QStringLiteral("^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$"), + QStringLiteral(), + (SmartAttributeParsedData::SmartQuirk) + (SmartAttributeParsedData::SMART_QUIRK_3_UNUSED | + SmartAttributeParsedData::SMART_QUIRK_4_UNUSED | + SmartAttributeParsedData::SMART_QUIRK_225_TOTALLBASWRITTEN | + SmartAttributeParsedData::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR | + SmartAttributeParsedData::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS | + SmartAttributeParsedData::SMART_QUIRK_228_WORKLOADTIMER | + SmartAttributeParsedData::SMART_QUIRK_232_AVAILABLERESERVEDSPACE | + SmartAttributeParsedData::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR)); return quirkDb; } static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware) { - const SmartAttributeParsedData::SmartQuirkDataBase *db; + const QVector db = quirkDatabase(); QRegularExpression modelRegex; QRegularExpression firmwareRegex; - for (db = quirkDatabase(); db->model || db->firmware; db++) { - if (db->model) { - modelRegex.setPattern(QString::fromLocal8Bit(db->model)); + for (const SmartAttributeParsedData::SmartQuirkDataBase &item : qAsConst(db)) { + if (!item.model.isEmpty()) { + modelRegex.setPattern(item.model); QRegularExpressionMatch match = modelRegex.match(model); if (!match.hasMatch()) continue; } - if (db->firmware) { - firmwareRegex.setPattern(QString::fromLocal8Bit(db->firmware)); + if (!item.firmware.isEmpty()) { + firmwareRegex.setPattern(item.firmware); QRegularExpressionMatch match = firmwareRegex.match(firmware); if (!match.hasMatch()) continue; } - return db->quirk; + return item.quirk; } return (SmartAttributeParsedData::SmartQuirk) 0; diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index d11a6bb..5116aa3 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -74,9 +74,18 @@ public: /** SMART Quirk to some particular model and firmware */ struct SmartQuirkDataBase { - const char *model; - const char *firmware; + QString model; + QString firmware; SmartAttributeParsedData::SmartQuirk quirk; + + SmartQuirkDataBase(const QString &m = QString(), + const QString &f = QString(), + SmartAttributeParsedData::SmartQuirk q = (SmartAttributeParsedData::SmartQuirk) 0) : + model(m), + firmware(f), + quirk(q) + { + }; }; public: From e3aae714a205f6c15a0e7880194b5b76ee67dc81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 24 Mar 2018 18:27:00 +0000 Subject: [PATCH 058/175] Remove unnecessary whitespace. --- src/core/smartattributeparseddata.cpp | 26 +++++++++++++------------- src/core/smartattributeparseddata.h | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index d3e832f..b14e520 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -481,7 +481,7 @@ static const QMap tableUni static const QVector quirkDatabase() { typedef SmartAttributeParsedData::SmartQuirkDataBase QuirkDatabase; - + QVector quirkDb; quirkDb << QuirkDatabase(QStringLiteral("^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$"), QStringLiteral("^0085000B$"), @@ -499,7 +499,7 @@ static const QVector quirkDatabase SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT | SmartAttributeParsedData::SMART_QUIRK_201_DETECTEDTACOUNT)); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "FUJITSU M1623TAU|" "FUJITSU MHG2...ATU?.*|" @@ -517,14 +517,14 @@ static const QVector quirkDatabase ")$"), QStringLiteral(), SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "SAMSUNG SV4012H|" "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]" ")$"), QStringLiteral(), SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "SAMSUNG SV0412H|" "SAMSUNG SV1204H" @@ -532,19 +532,19 @@ static const QVector quirkDatabase QStringLiteral(), (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES | SmartAttributeParsedData::SMART_QUIRK_194_10XCELSIUS)); - + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP40A2H$"), QStringLiteral("^RR100-07$"), SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); - + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP80A4H$"), QStringLiteral("^RT100-06$"), SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); - + quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP8004H$"), QStringLiteral("^QW100-61$"), SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "Maxtor 2B0(0[468]|1[05]|20)H1|" "Maxtor 4G(120J6|160J[68])|" @@ -553,7 +553,7 @@ static const QVector quirkDatabase QStringLiteral(), (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | SmartAttributeParsedData::SMART_QUIRK_194_UNKNOWN)); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "Maxtor 2F0[234]0[JL]0|" "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|" @@ -586,7 +586,7 @@ static const QVector quirkDatabase ")$"), QStringLiteral(), SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES); - + quirkDb << QuirkDatabase(QStringLiteral("^(" "HITACHI_DK14FA-20B|" "HITACHI_DK23..-..B?|" @@ -597,16 +597,16 @@ static const QVector quirkDatabase QStringLiteral(), (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | SmartAttributeParsedData::SMART_QUIRK_193_LOADUNLOAD)); - + quirkDb << QuirkDatabase(QStringLiteral("^HTS541010G9SA00$"), QStringLiteral("^MBZOC60P$"), SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN); - + quirkDb << QuirkDatabase(QStringLiteral("^MCCOE64GEMPP$"), QStringLiteral("^2.9.0[3-9]$"), (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN | SmartAttributeParsedData::SMART_QUIRK_190_UNKNOWN)); - + quirkDb << QuirkDatabase(QStringLiteral("^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$"), QStringLiteral(), (SmartAttributeParsedData::SmartQuirk) diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index 5116aa3..ef3ed51 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -77,9 +77,9 @@ public: QString model; QString firmware; SmartAttributeParsedData::SmartQuirk quirk; - - SmartQuirkDataBase(const QString &m = QString(), - const QString &f = QString(), + + SmartQuirkDataBase(const QString &m = QString(), + const QString &f = QString(), SmartAttributeParsedData::SmartQuirk q = (SmartAttributeParsedData::SmartQuirk) 0) : model(m), firmware(f), From 9218b55c578d1355f255090a7fb9e5138933cc4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 28 Mar 2018 02:15:46 +0100 Subject: [PATCH 059/175] Exit even loop if KAuth job finishes with error. --- src/backend/corebackendmanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index f2ab2b7..89caf92 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -78,6 +78,7 @@ void CoreBackendManager::startExternalCommandHelper() QEventLoop loop; auto exitLoop = [&] () {loop.exit();}; auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); + QObject::connect(job(), &KJob::finished, [=] () { if(job()->error()) exitLoop(); } ); loop.exec(); QObject::disconnect(conn); From 8f88efeefd8580ce4d10575f406f7ad818dc4ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 12:56:34 +0100 Subject: [PATCH 060/175] Use std::unique_ptr in CoreBackend. --- src/backend/corebackend.cpp | 3 +-- src/backend/corebackend.h | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backend/corebackend.cpp b/src/backend/corebackend.cpp index 9ce45c0..9c1d42e 100644 --- a/src/backend/corebackend.cpp +++ b/src/backend/corebackend.cpp @@ -31,13 +31,12 @@ public: }; CoreBackend::CoreBackend() : - d(new CoreBackendPrivate()) + d(std::make_unique()) { } CoreBackend::~CoreBackend() { - delete d; } void CoreBackend::emitProgress(int i) diff --git a/src/backend/corebackend.h b/src/backend/corebackend.h index 7829ce2..92c1bb8 100644 --- a/src/backend/corebackend.h +++ b/src/backend/corebackend.h @@ -23,6 +23,8 @@ #include "util/libpartitionmanagerexport.h" #include "fs/filesystem.h" +#include + #include #include @@ -187,7 +189,7 @@ private: QString m_id, m_version; class CoreBackendPrivate; - CoreBackendPrivate* d; + std::unique_ptr d; }; #endif From 00cb2c85d96b0d27393f482827f25a65d260e852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 13:05:34 +0100 Subject: [PATCH 061/175] d-pointerize CoreBackendManager --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 3 ++- src/backend/corebackendmanager.cpp | 25 ++++++++++++++++--------- src/backend/corebackendmanager.h | 19 +++++++------------ src/backend/corebackendmanager_p.h | 30 ++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 +- 6 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 src/backend/corebackendmanager_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f6b5a63..ddb5423 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ set(VERSION_MAJOR "3") set(VERSION_MINOR "3") set(VERSION_RELEASE "0") set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}) -set(SOVERSION "8") +set(SOVERSION "9") add_definitions(-D'VERSION="${VERSION}"') #" set(CMAKE_CXX_STANDARD 14) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b6365a..00b1b91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,10 +43,11 @@ target_link_libraries( kpmcore PUBLIC ${UUID_LIBRARIES} ${BLKID_LIBRARIES} Qt5::DBus - KF5::Auth KF5::I18n KF5::CoreAddons KF5::WidgetsAddons + PRIVATE + KF5::Auth ) install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 89caf92..d961404 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -18,6 +18,7 @@ *************************************************************************/ #include "backend/corebackendmanager.h" +#include "backend/corebackendmanager_p.h" #include "backend/corebackend.h" #include @@ -36,7 +37,7 @@ #include CoreBackendManager::CoreBackendManager() : - m_Backend(nullptr) + d(std::make_unique()) { startExternalCommandHelper(); } @@ -51,6 +52,10 @@ CoreBackendManager* CoreBackendManager::self() return instance; } +CoreBackend* CoreBackendManager::backend() { + return d->m_Backend; +} + QVector CoreBackendManager::list() const { auto filter = [&](const KPluginMetaData &metaData) { @@ -68,17 +73,17 @@ void CoreBackendManager::startExternalCommandHelper() action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days QVariantMap arguments; - m_Uuid = QUuid::createUuid().toString(); + d->m_Uuid = QUuid::createUuid().toString(); arguments.insert(QStringLiteral("callerUuid"), Uuid()); action.setArguments(arguments); - m_job = action.execute(); + d->m_job = action.execute(); job()->start(); // Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop) QEventLoop loop; - auto exitLoop = [&] () {loop.exit();}; + auto exitLoop = [&] () { loop.exit(); }; auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); - QObject::connect(job(), &KJob::finished, [=] () { if(job()->error()) exitLoop(); } ); + QObject::connect(job(), &KJob::finished, [=] () { if(d->m_job->error()) exitLoop(); } ); loop.exec(); QObject::disconnect(conn); @@ -107,7 +112,11 @@ void CoreBackendManager::stopExternalCommandHelper() } KAuth::ExecuteJob* CoreBackendManager::job() { - return m_job; + return d->m_job; +} + +QString& CoreBackendManager::Uuid() { + return d->m_Uuid; } bool CoreBackendManager::load(const QString& name) @@ -120,7 +129,7 @@ bool CoreBackendManager::load(const QString& name) KPluginFactory* factory = loader.factory(); if (factory != nullptr) { - m_Backend = factory->create(nullptr); + d->m_Backend = factory->create(nullptr); QString id = loader.metaData().toVariantMap().value(QStringLiteral("MetaData")) .toMap().value(QStringLiteral("KPlugin")).toMap().value(QStringLiteral("Id")).toString(); @@ -142,6 +151,4 @@ bool CoreBackendManager::load(const QString& name) void CoreBackendManager::unload() { - delete m_Backend; - m_Backend = nullptr; } diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index a754252..d623b53 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -16,13 +16,13 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_COREBACKENDMANAGER_H) +#ifndef KPMCORE_COREBACKENDMANAGER_H #define KPMCORE_COREBACKENDMANAGER_H #include "util/libpartitionmanagerexport.h" -#include +#include #include #include @@ -31,6 +31,8 @@ class QString; class QStringList; class KPluginMetaData; class CoreBackend; +namespace KAuth { class ExecuteJob; } +struct CoreBackendManagerPrivate; /** * The backend manager class. @@ -77,16 +79,12 @@ public: /** * @return a pointer to the currently loaded backend */ - CoreBackend* backend() { - return m_Backend; - } + CoreBackend* backend(); /** * @return a pointer to the currently loaded backend */ - QString& Uuid() { - return m_Uuid; - } + QString& Uuid(); /** * @return a pointer to the KAuth job @@ -102,10 +100,7 @@ private: void startExternalCommandHelper(); private: - CoreBackend *m_Backend; - KAuth::ExecuteJob *m_job; - - QString m_Uuid; + std::unique_ptr d; }; #endif diff --git a/src/backend/corebackendmanager_p.h b/src/backend/corebackendmanager_p.h new file mode 100644 index 0000000..0037ec5 --- /dev/null +++ b/src/backend/corebackendmanager_p.h @@ -0,0 +1,30 @@ +/************************************************************************* + * Copyright (C) 2018 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#if !defined(KPMCORE_COREBACKENDMANAGER_P_H) + +#define KPMCORE_COREBACKENDMANAGER_P_H + +struct CoreBackendManagerPrivate +{ + KAuth::ExecuteJob *m_job; + CoreBackend *m_Backend; + + QString m_Uuid; +}; + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 25151b8..f08c9af 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,7 +16,7 @@ add_compile_options(-fPIC) # and to add a test with the given name. # add_library(testhelpers STATIC helpers.cpp) -target_link_libraries(testhelpers KF5::Auth) +target_link_libraries(testhelpers) macro (kpm_test name) add_executable(${name} ${ARGN}) From 8fa1814f455d4b90609694d9c61b12b5ae5465fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 13:14:38 +0100 Subject: [PATCH 062/175] Remove libparted backend. --- src/backend/corebackendmanager_p.h | 2 +- src/plugins/CMakeLists.txt | 7 - src/plugins/libparted/CMakeLists.txt | 39 -- src/plugins/libparted/libpartedbackend.cpp | 601 ------------------ src/plugins/libparted/libpartedbackend.h | 80 --- src/plugins/libparted/libparteddevice.cpp | 112 ---- src/plugins/libparted/libparteddevice.h | 59 -- .../libparted/libpartedpartitiontable.cpp | 356 ----------- .../libparted/libpartedpartitiontable.h | 68 -- src/plugins/libparted/pedflags.h | 46 -- .../libparted/pmlibpartedbackendplugin.json | 48 -- 11 files changed, 1 insertion(+), 1417 deletions(-) delete mode 100644 src/plugins/libparted/CMakeLists.txt delete mode 100644 src/plugins/libparted/libpartedbackend.cpp delete mode 100644 src/plugins/libparted/libpartedbackend.h delete mode 100644 src/plugins/libparted/libparteddevice.cpp delete mode 100644 src/plugins/libparted/libparteddevice.h delete mode 100644 src/plugins/libparted/libpartedpartitiontable.cpp delete mode 100644 src/plugins/libparted/libpartedpartitiontable.h delete mode 100644 src/plugins/libparted/pedflags.h delete mode 100644 src/plugins/libparted/pmlibpartedbackendplugin.json diff --git a/src/backend/corebackendmanager_p.h b/src/backend/corebackendmanager_p.h index 0037ec5..d28bcb4 100644 --- a/src/backend/corebackendmanager_p.h +++ b/src/backend/corebackendmanager_p.h @@ -15,7 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_COREBACKENDMANAGER_P_H) +#ifndef KPMCORE_COREBACKENDMANAGER_P_H #define KPMCORE_COREBACKENDMANAGER_P_H diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index a819359..098738c 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -15,13 +15,6 @@ ############################################ - -#option(PARTMAN_LIBPARTEDBACKEND "Build the libparted backend plugin." ON) - -#if (PARTMAN_LIBPARTEDBACKEND) -# add_subdirectory(libparted) -#endif (PARTMAN_LIBPARTEDBACKEND) - if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") option(PARTMAN_SFDISKBACKEND "Build the sfdisk backend plugin." ON) diff --git a/src/plugins/libparted/CMakeLists.txt b/src/plugins/libparted/CMakeLists.txt deleted file mode 100644 index abe9d81..0000000 --- a/src/plugins/libparted/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2010 by Volker Lanz -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -find_package(LIBPARTED REQUIRED) - -if (LIBPARTED_FILESYSTEM_SUPPORT) - add_definitions(-DLIBPARTED_FILESYSTEM_SUPPORT) -endif (LIBPARTED_FILESYSTEM_SUPPORT) - -if (LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) - add_definitions(-DLIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) -endif (LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) - -include_directories(${LIBPARTED_INCLUDE_DIR}) - -set (pmlibpartedbackendplugin_SRCS - libpartedbackend.cpp - libparteddevice.cpp - libpartedpartitiontable.cpp - ${CMAKE_SOURCE_DIR}/src/backend/corebackenddevice.cpp -) - -add_library(pmlibpartedbackendplugin SHARED ${pmlibpartedbackendplugin_SRCS}) - -target_link_libraries(pmlibpartedbackendplugin kpmcore ${LIBPARTED_LIBS} KF5::I18n) - -install(TARGETS pmlibpartedbackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR}) diff --git a/src/plugins/libparted/libpartedbackend.cpp b/src/plugins/libparted/libpartedbackend.cpp deleted file mode 100644 index 7c0e59a..0000000 --- a/src/plugins/libparted/libpartedbackend.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/************************************************************************* - * Copyright (C) 2008-2012 by Volker Lanz * - * Copyright (C) 2015-2016 by Teo Mrnjavac * - * Copyright (C) 2016-2017 by Andrius Štikonas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -/** @file -*/ - -#include "plugins/libparted/libpartedbackend.h" -#include "plugins/libparted/libparteddevice.h" -#include "plugins/libparted/pedflags.h" - -#include "core/lvmdevice.h" -#include "core/partition.h" -#include "core/partitiontable.h" -#include "core/partitionalignment.h" - -#include "fs/filesystem.h" -#include "fs/filesystemfactory.h" - -#include "fs/fat16.h" -#include "fs/hfs.h" -#include "fs/hfsplus.h" -#include "fs/luks.h" -#include "fs/lvm2_pv.h" - -#include "util/globallog.h" -#include "util/externalcommand.h" -#include "util/helpers.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -K_PLUGIN_FACTORY_WITH_JSON(LibPartedBackendFactory, "pmlibpartedbackendplugin.json", registerPlugin();) - -static QString s_lastPartedExceptionMessage; - -/** Callback to handle exceptions from libparted - @param e the libparted exception to handle -*/ -static PedExceptionOption pedExceptionHandler(PedException* e) -{ - Log(Log::error) << xi18nc("@info:status", "LibParted Exception: %1", QString::fromLocal8Bit(e->message)); - s_lastPartedExceptionMessage = QString::fromLocal8Bit(e->message); - return PED_EXCEPTION_UNHANDLED; -} - -// -------------------------------------------------------------------------- - -// The following structs and the typedef come from libparted's internal gpt sources. -// It's very unfortunate there is no public API to get at the first and last usable -// sector for GPT a partition table, so this is the only (libparted) way to get that -// information (another way would be to read the GPT header and parse the -// information ourselves; if the libparted devs begin changing these internal -// structs for each point release and break our code, we'll have to do just that). - -typedef struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node[6]; -} /* __attribute__ ((packed)) */ efi_guid_t; - - -struct __attribute__((packed)) _GPTDiskData { - PedGeometry data_area; - int entry_count; - efi_guid_t uuid; -}; - -typedef struct _GPTDiskData GPTDiskData; - -// -------------------------------------------------------------------------- - -/** Get the first sector a Partition may cover on a given Device - @param d the Device in question - @return the first sector usable by a Partition -*/ -static qint64 firstUsableSector(const Device& d) -{ - PedDevice* pedDevice = ped_device_get(d.deviceNode().toLocal8Bit().constData()); - PedDisk* pedDisk = pedDevice ? ped_disk_new(pedDevice) : nullptr; - - qint64 rval = 0; - if (pedDisk) - rval = static_cast(pedDisk->dev->bios_geom.sectors); - - if (pedDisk && strcmp(pedDisk->type->name, "gpt") == 0) { - GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); - PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); - - if (geom) - rval = static_cast(geom->start); - else - rval += 32; - } - - ped_disk_destroy(pedDisk); - - return rval; -} - -/** Get the last sector a Partition may cover on a given Device - @param d the Device in question - @return the last sector usable by a Partition -*/ -static qint64 lastUsableSector(const Device& d) -{ - PedDevice* pedDevice = ped_device_get(d.deviceNode().toLocal8Bit().constData()); - PedDisk* pedDisk = pedDevice ? ped_disk_new(pedDevice) : nullptr; - - qint64 rval = 0; - if (pedDisk) - rval = static_cast< qint64 >( pedDisk->dev->bios_geom.sectors ) * - static_cast< qint64 >( pedDisk->dev->bios_geom.heads ) * - static_cast< qint64 >( pedDisk->dev->bios_geom.cylinders - 1 ); - - if (pedDisk && strcmp(pedDisk->type->name, "gpt") == 0) { - GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); - PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); - - if (geom) - rval = geom->end; - else - rval -= 32; - } - - ped_disk_destroy(pedDisk); - - return rval; -} - -/** Reads sectors used on a FileSystem using libparted functions. - @param pedDisk pointer to pedDisk where the Partition and its FileSystem are - @param p the Partition the FileSystem is on - @return the number of sectors used -*/ -#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT -static qint64 readSectorsUsedLibParted(PedDisk* pedDisk, const Partition& p) -{ - Q_ASSERT(pedDisk); - - qint64 rval = -1; - - PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk, p.firstSector()); - - if (pedPartition) { - PedFileSystem* pedFileSystem = ped_file_system_open(&pedPartition->geom); - - if (pedFileSystem) { - if (PedConstraint* pedConstraint = ped_file_system_get_resize_constraint(pedFileSystem)) { - rval = pedConstraint->min_size; - ped_constraint_destroy(pedConstraint); - } - - ped_file_system_close(pedFileSystem); - } - } - - return rval; -} -#endif - -/** Reads the sectors used in a FileSystem and stores the result in the Partition's FileSystem object. - @param pedDisk pointer to pedDisk where the Partition and its FileSystem are - @param p the Partition the FileSystem is on - @param mountPoint mount point of the partition in question -*/ -static void readSectorsUsed(PedDisk* pedDisk, const Device& d, Partition& p, const QString& mountPoint) -{ - if (!mountPoint.isEmpty() && p.fileSystem().type() != FileSystem::LinuxSwap && p.fileSystem().type() != FileSystem::Lvm2_PV) { - const QStorageInfo storage = QStorageInfo(mountPoint); - if (p.isMounted() && storage.isValid()) - p.fileSystem().setSectorsUsed( (storage.bytesTotal() - storage.bytesFree()) / d.logicalSize()); - } - else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportFileSystem) - p.fileSystem().setSectorsUsed(p.fileSystem().readUsedCapacity(p.deviceNode()) / d.logicalSize()); -#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT - else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportCore) - p.fileSystem().setSectorsUsed(readSectorsUsedLibParted(pedDisk, p)); -#else - Q_UNUSED(pedDisk); -#endif -} - -static PartitionTable::Flags activeFlags(PedPartition* p) -{ - PartitionTable::Flags flags = PartitionTable::FlagNone; - - // We might get here with a pedPartition just picked up from libparted that is - // unallocated. Libparted doesn't like it if we ask for flags for unallocated - // space. - if (p->num <= 0) - return flags; - - for (const auto &flag : flagmap) - if (ped_partition_is_flag_available(p, flag.pedFlag) && ped_partition_get_flag(p, flag.pedFlag)) - flags |= flag.flag; - - return flags; -} - -static PartitionTable::Flags availableFlags(PedPartition* p) -{ - PartitionTable::Flags flags; - - // see above. - if (p->num <= 0) - return flags; - - for (const auto &flag : flagmap) { - if (ped_partition_is_flag_available(p, flag.pedFlag)) { - // Workaround: libparted claims the hidden flag is available for extended partitions, but - // throws an error when we try to set or clear it. So skip this combination. Also see setFlag. - if (p->type != PED_PARTITION_EXTENDED || flag.flag != PartitionTable::FlagHidden) - flags |= flag.flag; - } - } - - return flags; -} - -/** Constructs a LibParted object. */ -LibPartedBackend::LibPartedBackend(QObject*, const QList&) : - CoreBackend() -{ - ped_exception_set_handler(pedExceptionHandler); -} - -void LibPartedBackend::initFSSupport() -{ -#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT - if (FS::fat16::m_Shrink == FileSystem::cmdSupportNone) - FS::fat16::m_Shrink = FileSystem::cmdSupportBackend; - - if (FS::fat16::m_Grow == FileSystem::cmdSupportNone) - FS::fat16::m_Grow = FileSystem::cmdSupportBackend; - - if (FS::hfs::m_Shrink == FileSystem::cmdSupportNone) - FS::hfs::m_Shrink = FileSystem::cmdSupportBackend; - - if (FS::hfsplus::m_Shrink == FileSystem::cmdSupportNone) - FS::hfsplus::m_Shrink = FileSystem::cmdSupportBackend; - - if (FS::hfs::m_GetUsed == FileSystem::cmdSupportNone) - FS::hfs::m_GetUsed = FileSystem::cmdSupportBackend; - - if (FS::hfsplus::m_GetUsed == FileSystem::cmdSupportNone) - FS::hfsplus::m_GetUsed = FileSystem::cmdSupportBackend; -#endif -} - -/** Scans a Device for Partitions. - - This method will scan a Device for all Partitions on it, detect the FileSystem for each Partition, - try to determine the FileSystem usage, read the FileSystem label and store it all in newly created - objects that are in the end added to the Device's PartitionTable. - - @param d Device - @param pedDisk libparted pointer to the partition table -*/ -void LibPartedBackend::scanDevicePartitions(Device& d, PedDisk* pedDisk) -{ - Q_ASSERT(pedDisk); - Q_ASSERT(d.partitionTable()); - - PedPartition* pedPartition = nullptr; - - QList partitions; - - while ((pedPartition = ped_disk_next_partition(pedDisk, pedPartition))) { - if (pedPartition->num < 1) - continue; - - PartitionRole::Roles r = PartitionRole::None; - - FileSystem::Type type = FileSystem::Unknown; - char* pedPath = ped_partition_get_path(pedPartition); - const QString partitionNode = pedPath ? QString::fromLocal8Bit(pedPath) : QString(); - free(pedPath); - type = detectFileSystem(partitionNode); - - switch (pedPartition->type) { - case PED_PARTITION_NORMAL: - r = PartitionRole::Primary; - break; - - case PED_PARTITION_EXTENDED: - r = PartitionRole::Extended; - type = FileSystem::Extended; - break; - - case PED_PARTITION_LOGICAL: - r = PartitionRole::Logical; - break; - - default: - continue; - } - - // Find an extended partition this partition is in. - PartitionNode* parent = d.partitionTable()->findPartitionBySector(pedPartition->geom.start, PartitionRole(PartitionRole::Extended)); - - // None found, so it's a primary in the device's partition table. - if (parent == nullptr) - parent = d.partitionTable(); - - FileSystem* fs = FileSystemFactory::create(type, pedPartition->geom.start, pedPartition->geom.end, d.logicalSize()); - fs->scan(partitionNode); - QString mountPoint; - bool mounted; - - // libparted does not handle LUKS partitions - if (fs->type() == FileSystem::Luks) { - r |= PartitionRole::Luks; - FS::luks* luksFs = static_cast(fs); - luksFs->initLUKS(); - QString mapperNode = luksFs->mapperName(); - mountPoint = FileSystem::detectMountPoint(fs, mapperNode); - mounted = FileSystem::detectMountStatus(fs, mapperNode); - } else { - mountPoint = FileSystem::detectMountPoint(fs, partitionNode); - mounted = FileSystem::detectMountStatus(fs, partitionNode); - } - - Partition* part = new Partition(parent, d, PartitionRole(r), fs, pedPartition->geom.start, pedPartition->geom.end, partitionNode, availableFlags(pedPartition), mountPoint, mounted, activeFlags(pedPartition)); - - if (!part->roles().has(PartitionRole::Luks)) - readSectorsUsed(pedDisk, d, *part, mountPoint); - - if (fs->supportGetLabel() != FileSystem::cmdSupportNone) - fs->setLabel(fs->readLabel(part->deviceNode())); - - // GPT partitions support partition labels and partition UUIDs - if(d.partitionTable()->type() == PartitionTable::TableType::gpt) - part->setLabel(QLatin1String(ped_partition_get_name(pedPartition))); - - if (fs->supportGetUUID() != FileSystem::cmdSupportNone) - fs->setUUID(fs->readUUID(part->deviceNode())); - - parent->append(part); - partitions.append(part); - } - - d.partitionTable()->updateUnallocated(d); - - if (d.partitionTable()->isSectorBased(d)) - d.partitionTable()->setType(d, PartitionTable::msdos_sectorbased); - - for (const Partition * part : qAsConst(partitions)) - PartitionAlignment::isAligned(d, *part); -} - -/** Create a Device for the given device_node and scan it for partitions. - @param deviceNode the device node (e.g. "/dev/sda") - @return the created Device object. callers need to free this. -*/ -DiskDevice* LibPartedBackend::scanDevice(const QString& deviceNode) -{ - PedDevice* pedDevice = ped_device_get(deviceNode.toLocal8Bit().constData()); - - if (pedDevice == nullptr) { - Log(Log::warning) << xi18nc("@info:status", "Could not access device %1", deviceNode); - return nullptr; - } - - Log(Log::information) << xi18nc("@info:status", "Device found: %1", QString::fromLocal8Bit(pedDevice->model)); - - DiskDevice* d = new DiskDevice(QString::fromLocal8Bit(pedDevice->model), QString::fromLocal8Bit(pedDevice->path), pedDevice->bios_geom.heads, pedDevice->bios_geom.sectors, pedDevice->bios_geom.cylinders, pedDevice->sector_size); - - PedDisk* pedDisk = ped_disk_new(pedDevice); - - if (pedDisk) { - const PartitionTable::TableType type = PartitionTable::nameToTableType(QString::fromLocal8Bit(pedDisk->type->name)); - CoreBackend::setPartitionTableForDevice(*d, new PartitionTable(type, firstUsableSector(*d), lastUsableSector(*d))); - CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), ped_disk_get_max_primary_partition_count(pedDisk)); - - scanDevicePartitions(*d, pedDisk); - } - - ped_device_destroy(pedDevice); - return d; -} - -QList LibPartedBackend::scanDevices(bool excludeReadOnly) -{ -// TODO: add another bool option for loopDevices - QList result; - QStringList deviceNodes; - - ExternalCommand cmd(QStringLiteral("lsblk"), - { QStringLiteral("--nodeps"), - QStringLiteral("--paths"), - QStringLiteral("--sort"), QStringLiteral("name"), - QStringLiteral("--json"), - QStringLiteral("--output"), - QStringLiteral("type,name") }); - - if (cmd.run(-1) && cmd.exitCode() == 0) { - const QJsonDocument jsonDocument = QJsonDocument::fromJson(cmd.rawOutput()); - QJsonObject jsonObject = jsonDocument.object(); - const QJsonArray jsonArray = jsonObject[QLatin1String("blockdevices")].toArray(); - for (const auto &deviceLine : jsonArray) { - QJsonObject deviceObject = deviceLine.toObject(); - if (deviceObject[QLatin1String("type")].toString() != QLatin1String("disk")) - continue; - - const QString deviceNode = deviceObject[QLatin1String("name")].toString(); - if (excludeReadOnly) { - QString deviceName = deviceNode; - deviceName.remove(QStringLiteral("/dev/")); - QFile f(QStringLiteral("/sys/block/%1/ro").arg(deviceName)); - if (f.open(QIODevice::ReadOnly)) - if (f.readLine().trimmed().toInt() == 1) - continue; - } - deviceNodes << deviceNode; - } - - int totalDevices = deviceNodes.length(); - for (int i = 0; i < totalDevices; ++i) { - const QString deviceNode = deviceNodes[i]; - - emitScanProgress(deviceNode, i * 100 / totalDevices); - Device* device = scanDevice(deviceNode); - if(device != nullptr) { - result.append(device); - } - } - - LvmDevice::scanSystemLVM(result); - } - - return result; -} - -/** Detects the type of a FileSystem given a PedDevice and a PedPartition - @param partitionPath path to the partition - @return the detected FileSystem type (FileSystem::Unknown if not detected) -*/ -FileSystem::Type LibPartedBackend::detectFileSystem(const QString& partitionPath) -{ - FileSystem::Type rval = FileSystem::Unknown; - - blkid_cache cache; - if (blkid_get_cache(&cache, nullptr) == 0) { - blkid_dev dev; - - if ((dev = blkid_get_dev(cache, - partitionPath.toLocal8Bit().constData(), - BLKID_DEV_NORMAL)) != nullptr) { - char *string = blkid_get_tag_value(cache, "TYPE", partitionPath.toLocal8Bit().constData()); - QString s = QString::fromLocal8Bit(string); - free(string); - - if (s == QStringLiteral("ext2")) rval = FileSystem::Ext2; - else if (s == QStringLiteral("ext3")) rval = FileSystem::Ext3; - else if (s.startsWith(QStringLiteral("ext4"))) rval = FileSystem::Ext4; - else if (s == QStringLiteral("swap")) rval = FileSystem::LinuxSwap; - else if (s == QStringLiteral("ntfs")) rval = FileSystem::Ntfs; - else if (s == QStringLiteral("reiserfs")) rval = FileSystem::ReiserFS; - else if (s == QStringLiteral("reiser4")) rval = FileSystem::Reiser4; - else if (s == QStringLiteral("xfs")) rval = FileSystem::Xfs; - else if (s == QStringLiteral("jfs")) rval = FileSystem::Jfs; - else if (s == QStringLiteral("hfs")) rval = FileSystem::Hfs; - else if (s == QStringLiteral("hfsplus")) rval = FileSystem::HfsPlus; - else if (s == QStringLiteral("ufs")) rval = FileSystem::Ufs; - else if (s == QStringLiteral("vfat")) { - // libblkid uses SEC_TYPE to distinguish between FAT16 and FAT32 - string = blkid_get_tag_value(cache, "SEC_TYPE", partitionPath.toLocal8Bit().constData()); - QString st = QString::fromLocal8Bit(string); - free(string); - if (st == QStringLiteral("msdos")) - rval = FileSystem::Fat16; - else - rval = FileSystem::Fat32; - } else if (s == QStringLiteral("btrfs")) rval = FileSystem::Btrfs; - else if (s == QStringLiteral("ocfs2")) rval = FileSystem::Ocfs2; - else if (s == QStringLiteral("zfs_member")) rval = FileSystem::Zfs; - else if (s == QStringLiteral("hpfs")) rval = FileSystem::Hpfs; - else if (s == QStringLiteral("crypto_LUKS")) rval = FileSystem::Luks; - else if (s == QStringLiteral("exfat")) rval = FileSystem::Exfat; - else if (s == QStringLiteral("nilfs2")) rval = FileSystem::Nilfs2; - else if (s == QStringLiteral("LVM2_member")) rval = FileSystem::Lvm2_PV; - else if (s == QStringLiteral("f2fs")) rval = FileSystem::F2fs; - else if (s == QStringLiteral("udf")) rval = FileSystem::Udf; - else if (s == QStringLiteral("iso9660")) rval = FileSystem::Iso9660; - else - qWarning() << "blkid: unknown file system type " << s << " on " << partitionPath; - } - - blkid_put_cache(cache); - } - - return rval; -} - -static QString readBlkIdValue(const QString& deviceNode, const QString& tag) -{ - blkid_cache cache; - QString rval; - - if (blkid_get_cache(&cache, nullptr) == 0) { - blkid_dev dev; - - char* label = nullptr; - if ((dev = blkid_get_dev(cache, deviceNode.toLocal8Bit().constData(), BLKID_DEV_NORMAL)) != nullptr && - (label = blkid_get_tag_value(cache, tag.toLocal8Bit().constData(), deviceNode.toLocal8Bit().constData()))) { - rval = QString::fromLocal8Bit(label); - free(label); - } - - blkid_put_cache(cache); - } - - return rval; -} - -QString LibPartedBackend::readLabel(const QString& deviceNode) const -{ - return readBlkIdValue(deviceNode, QStringLiteral("LABEL")); -} - -QString LibPartedBackend::readUUID(const QString& deviceNode) const -{ - return readBlkIdValue(deviceNode, QStringLiteral("UUID")); -} - -CoreBackendDevice* LibPartedBackend::openDevice(const Device& d) -{ - LibPartedDevice* device = new LibPartedDevice(d.deviceNode()); - - if (device == nullptr || !device->open()) { - delete device; - device = nullptr; - } - - return device; -} - -CoreBackendDevice* LibPartedBackend::openDeviceExclusive(const Device& d) -{ - LibPartedDevice* device = new LibPartedDevice(d.deviceNode()); - - if (device == nullptr || !device->openExclusive()) { - delete device; - device = nullptr; - } - - return device; -} - -bool LibPartedBackend::closeDevice(CoreBackendDevice* core_device) -{ - return core_device->close(); -} - -PedPartitionFlag LibPartedBackend::getPedFlag(PartitionTable::Flag flag) -{ - for (const auto &f : flagmap) - if (f.flag == flag) - return f.pedFlag; - - return static_cast(-1); -} - -QString LibPartedBackend::lastPartedExceptionMessage() -{ - return s_lastPartedExceptionMessage; -} - -#include "libpartedbackend.moc" diff --git a/src/plugins/libparted/libpartedbackend.h b/src/plugins/libparted/libpartedbackend.h deleted file mode 100644 index 93ed320..0000000 --- a/src/plugins/libparted/libpartedbackend.h +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************* - * Copyright (C) 2008, 2010 by Volker Lanz * - * Copyright (C) 2015 by Teo Mrnjavac * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#if !defined(KPMCORE_LIBPARTED_H) - -#define KPMCORE_LIBPARTED_H - -#include "backend/corebackend.h" - -#include "core/partitiontable.h" -#include "core/diskdevice.h" -#include "util/libpartitionmanagerexport.h" - -#include "fs/filesystem.h" - -#include - -#include -#include -#include - -class LibPartedDevice; -class LibPartedPartitionTable; -class LibPartedPartition; -class OperationStack; - -class KPluginFactory; -class QString; - -/** Backend plugin for libparted. - - @author Volker Lanz -*/ -class LibPartedBackend : public CoreBackend -{ - friend class KPluginFactory; - friend class LibPartedPartition; - friend class LibPartedDevice; - friend class LibPartedPartitionTable; - - Q_DISABLE_COPY(LibPartedBackend) - -private: - LibPartedBackend(QObject* parent, const QList& args); - -public: - void initFSSupport() override; - - CoreBackendDevice* openDevice(const Device& d) override; - CoreBackendDevice* openDeviceExclusive(const Device& d) override; - bool closeDevice(CoreBackendDevice* core_device) override; - DiskDevice* scanDevice(const QString& deviceNode) override; - QList scanDevices(bool excludeReadOnly = false) override; - FileSystem::Type detectFileSystem(const QString& partitionPath) override; - QString readLabel(const QString& deviceNode) const override; - QString readUUID(const QString& deviceNode) const override; - - static QString lastPartedExceptionMessage(); - -private: - static PedPartitionFlag getPedFlag(PartitionTable::Flag flag); - void scanDevicePartitions(Device& d, PedDisk* pedDisk); -}; - -#endif diff --git a/src/plugins/libparted/libparteddevice.cpp b/src/plugins/libparted/libparteddevice.cpp deleted file mode 100644 index d97e41c..0000000 --- a/src/plugins/libparted/libparteddevice.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/************************************************************************* - * Copyright (C) 2010 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#include "plugins/libparted/libparteddevice.h" -#include "plugins/libparted/libpartedpartitiontable.h" - -#include "core/partitiontable.h" - -#include "util/globallog.h" -#include "util/report.h" - -#include - -LibPartedDevice::LibPartedDevice(const QString& deviceNode) : - CoreBackendDevice(deviceNode), - m_PedDevice(nullptr) -{ -} - -LibPartedDevice::~LibPartedDevice() -{ - if (pedDevice()) - close(); -} - -bool LibPartedDevice::open() -{ - Q_ASSERT(pedDevice() == nullptr); - - if (pedDevice()) - return false; - - m_PedDevice = ped_device_get(deviceNode().toLocal8Bit().constData()); - - return m_PedDevice != nullptr; -} - -bool LibPartedDevice::openExclusive() -{ - bool rval = open() && ped_device_open(pedDevice()); - - if (rval) - setExclusive(true); - - return rval; -} - -bool LibPartedDevice::close() -{ - Q_ASSERT(pedDevice()); - - if (pedDevice() && isExclusive()) { - ped_device_close(pedDevice()); - setExclusive(false); - } - - m_PedDevice = nullptr; - return true; -} - -CoreBackendPartitionTable* LibPartedDevice::openPartitionTable() -{ - CoreBackendPartitionTable* ptable = new LibPartedPartitionTable(pedDevice()); - - if (ptable == nullptr || !ptable->open()) { - delete ptable; - ptable = nullptr; - } - - return ptable; -} - -bool LibPartedDevice::createPartitionTable(Report& report, const PartitionTable& ptable) -{ - PedDiskType* pedDiskType = ped_disk_type_get(ptable.typeName().toLocal8Bit().constData()); - - if (pedDiskType == nullptr) { - report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not retrieve partition table type \"%1\" for %2.", ptable.typeName(), deviceNode()); - return false; - } - - PedDevice* dev = ped_device_get(deviceNode().toLocal8Bit().constData()); - - if (dev == nullptr) { - report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not open backend device %1.", deviceNode()); - return false; - } - - PedDisk* disk = ped_disk_new_fresh(dev, pedDiskType); - - if (disk == nullptr) { - report.line() << xi18nc("@info:progress", "Creating partition table failed: Could not create a new partition table in the backend for device %1.", deviceNode()); - return false; - } - - return LibPartedPartitionTable::commit(disk); -} diff --git a/src/plugins/libparted/libparteddevice.h b/src/plugins/libparted/libparteddevice.h deleted file mode 100644 index dc8f16a..0000000 --- a/src/plugins/libparted/libparteddevice.h +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************************************* - * Copyright (C) 2010 by Volker Lanz * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#if !defined(KPMCORE_LIBPARTEDDEVICE_H) - -#define KPMCORE_LIBPARTEDDEVICE_H - -#include "backend/corebackenddevice.h" - -#include - -#include - -class Partition; -class PartitionTable; -class Report; -class CoreBackendPartitionTable; - -class LibPartedDevice : public CoreBackendDevice -{ - Q_DISABLE_COPY(LibPartedDevice) - -public: - LibPartedDevice(const QString& deviceNode); - ~LibPartedDevice(); - -public: - bool open() override; - bool openExclusive() override; - bool close() override; - - CoreBackendPartitionTable* openPartitionTable() override; - - bool createPartitionTable(Report& report, const PartitionTable& ptable) override; - -protected: - PedDevice* pedDevice() { - return m_PedDevice; - } - -private: - PedDevice* m_PedDevice; -}; - -#endif diff --git a/src/plugins/libparted/libpartedpartitiontable.cpp b/src/plugins/libparted/libpartedpartitiontable.cpp deleted file mode 100644 index 79074ea..0000000 --- a/src/plugins/libparted/libpartedpartitiontable.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/************************************************************************* - * Copyright (C) 2010, 2011, 2012 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#include "plugins/libparted/libpartedpartitiontable.h" -#include "plugins/libparted/libpartedbackend.h" - -#include "backend/corebackend.h" -#include "backend/corebackendmanager.h" - -#include "core/partition.h" -#include "core/device.h" - -#include "fs/filesystem.h" - -#include "util/report.h" -#include "util/externalcommand.h" - -#include - -#include - -LibPartedPartitionTable::LibPartedPartitionTable(PedDevice* device) : - CoreBackendPartitionTable(), - m_PedDevice(device), - m_PedDisk(nullptr) -{ -} - -LibPartedPartitionTable::~LibPartedPartitionTable() -{ - ped_disk_destroy(m_PedDisk); -} - -bool LibPartedPartitionTable::open() -{ - m_PedDisk = ped_disk_new(pedDevice()); - - return m_PedDisk != nullptr; -} - -bool LibPartedPartitionTable::commit(quint32 timeout) -{ - return commit(pedDisk(), timeout); -} - -bool LibPartedPartitionTable::commit(PedDisk* pd, quint32 timeout) -{ - if (pd == nullptr) - return false; - - bool rval = ped_disk_commit_to_dev(pd); - - if (rval) - rval = ped_disk_commit_to_os(pd); - - if (!ExternalCommand(QStringLiteral("udevadm"), QStringList() << QStringLiteral("settle") << QStringLiteral("--timeout=") + QString::number(timeout)).run() && - !ExternalCommand(QStringLiteral("udevsettle"), QStringList() << QStringLiteral("--timeout=") + QString::number(timeout)).run()) - sleep(timeout); - - return rval; -} - -static const struct { - FileSystem::Type type; - QString name; -} mapFileSystemTypeToLibPartedName[] = { - { FileSystem::Btrfs, QStringLiteral("btrfs") }, - { FileSystem::Ext2, QStringLiteral("ext2") }, - { FileSystem::Ext3, QStringLiteral("ext3") }, - { FileSystem::Ext4, QStringLiteral("ext4") }, - { FileSystem::LinuxSwap, QStringLiteral("linux-swap") }, - { FileSystem::Fat16, QStringLiteral("fat16") }, - { FileSystem::Fat32, QStringLiteral("fat32") }, - { FileSystem::Nilfs2, QStringLiteral("nilfs2") }, - { FileSystem::Ntfs, QStringLiteral("ntfs") }, - { FileSystem::Exfat, QStringLiteral("ntfs") }, - { FileSystem::ReiserFS, QStringLiteral("reiserfs") }, - { FileSystem::Reiser4, QStringLiteral("reiserfs") }, - { FileSystem::Xfs, QStringLiteral("xfs") }, - { FileSystem::Jfs, QStringLiteral("jfs") }, - { FileSystem::Hfs, QStringLiteral("hfs") }, - { FileSystem::HfsPlus, QStringLiteral("hfs+") }, - { FileSystem::Ufs, QStringLiteral("ufs") }, - { FileSystem::Udf, QStringLiteral("ntfs") }, - { FileSystem::Iso9660, QStringLiteral("iso9660") } -}; - -static PedFileSystemType* getPedFileSystemType(FileSystem::Type t) -{ - for (quint32 i = 0; i < sizeof(mapFileSystemTypeToLibPartedName) / sizeof(mapFileSystemTypeToLibPartedName[0]); i++) - if (mapFileSystemTypeToLibPartedName[i].type == t) - return ped_file_system_type_get(mapFileSystemTypeToLibPartedName[i].name.toLocal8Bit().constData()); - - // if we didn't find anything, go with ext2 as a safe fallback - return ped_file_system_type_get("ext2"); -} - -QString LibPartedPartitionTable::createPartition(Report& report, const Partition& partition) -{ - Q_ASSERT(partition.devicePath() == QString::fromLocal8Bit(pedDevice()->path)); - - QString rval = QString(); - - // According to libParted docs, PedPartitionType can be "nullptr if unknown". That's obviously wrong, - // it's a typedef for an enum. So let's use something the libparted devs will hopefully never - // use... - PedPartitionType pedType = static_cast(0xffffffff); - - if (partition.roles().has(PartitionRole::Extended)) - pedType = PED_PARTITION_EXTENDED; - else if (partition.roles().has(PartitionRole::Logical)) - pedType = PED_PARTITION_LOGICAL; - else if (partition.roles().has(PartitionRole::Primary)) - pedType = PED_PARTITION_NORMAL; - - if (pedType == static_cast(0xffffffff)) { - report.line() << xi18nc("@info:progress", "Unknown partition role for new partition %1 (roles: %2)", partition.deviceNode(), partition.roles().toString()); - return QString(); - } - - PedFileSystemType* pedFsType = (partition.roles().has(PartitionRole::Extended) || partition.fileSystem().type() == FileSystem::Unformatted) ? nullptr : getPedFileSystemType(partition.fileSystem().type()); - - PedPartition* pedPartition = ped_partition_new(pedDisk(), pedType, pedFsType, partition.firstSector(), partition.lastSector()); - - if (pedPartition == nullptr) { - report.line() << xi18nc("@info:progress", "Failed to create new partition %1.", partition.deviceNode()); - return QString(); - } - - PedConstraint* pedConstraint = nullptr; - PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), partition.firstSector(), partition.length()); - - if (pedGeometry) - pedConstraint = ped_constraint_exact(pedGeometry); - ped_geometry_destroy(pedGeometry); - - if (pedConstraint == nullptr) { - report.line() << i18nc("@info:progress", "Failed to create a new partition: could not get geometry for constraint."); - return QString(); - } - - if (ped_disk_add_partition(pedDisk(), pedPartition, pedConstraint)) { - char *pedPath = ped_partition_get_path(pedPartition); - rval = QString::fromLocal8Bit(pedPath); - free(pedPath); - } - else { - report.line() << xi18nc("@info:progress", "Failed to add partition %1 to device %2.", partition.deviceNode(), QString::fromLocal8Bit(pedDisk()->dev->path)); - report.line() << LibPartedBackend::lastPartedExceptionMessage(); - } - - ped_constraint_destroy(pedConstraint); - - return rval; -} - -bool LibPartedPartitionTable::deletePartition(Report& report, const Partition& partition) -{ - Q_ASSERT(partition.devicePath() == QString::fromLocal8Bit(pedDevice()->path)); - - bool rval = false; - - PedPartition* pedPartition = partition.roles().has(PartitionRole::Extended) - ? ped_disk_extended_partition(pedDisk()) - : ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); - - if (pedPartition) { - rval = ped_disk_delete_partition(pedDisk(), pedPartition); - - if (!rval) - report.line() << xi18nc("@info:progress", "Could not delete partition %1.", partition.deviceNode()); - } else - report.line() << xi18nc("@info:progress", "Deleting partition failed: Partition to delete (%1) not found on disk.", partition.deviceNode()); - - return rval; -} - -bool LibPartedPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) -{ - Q_ASSERT(partition.devicePath() == QString::fromLocal8Bit(pedDevice()->path)); - - bool rval = false; - - PedPartition* pedPartition = (partition.roles().has(PartitionRole::Extended)) - ? ped_disk_extended_partition(pedDisk()) - : ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); - - if (pedPartition) { - if (PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), sector_start, sector_end - sector_start + 1)) { - if (PedConstraint* pedConstraint = ped_constraint_exact(pedGeometry)) { - if (ped_disk_set_partition_geom(pedDisk(), pedPartition, pedConstraint, sector_start, sector_end)) - rval = true; - else - report.line() << xi18nc("@info:progress", "Could not set geometry for partition %1 while trying to resize/move it.", partition.deviceNode()); - ped_constraint_destroy(pedConstraint); - } else - report.line() << xi18nc("@info:progress", "Could not get constraint for partition %1 while trying to resize/move it.", partition.deviceNode()); - ped_geometry_destroy(pedGeometry); - } else - report.line() << xi18nc("@info:progress", "Could not get geometry for partition %1 while trying to resize/move it.", partition.deviceNode()); - } else - report.line() << xi18nc("@info:progress", "Could not open partition %1 while trying to resize/move it.", partition.deviceNode()); - - return rval; -} - -bool LibPartedPartitionTable::clobberFileSystem(Report& report, const Partition& partition) -{ - bool rval = false; - - if (PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector())) { - if (pedPartition->type == PED_PARTITION_NORMAL || pedPartition->type == PED_PARTITION_LOGICAL) { - if (ped_device_open(pedDevice())) { - //reiser4 stores "ReIsEr4" at sector 128 with a sector size of 512 bytes - - // We need to use memset instead of = {0} because clang sucks. - const long long zeroes_length = pedDevice()->sector_size*129; - char* zeroes = new char[zeroes_length]; - memset(zeroes, 0, zeroes_length*sizeof(char)); - - rval = ped_geometry_write(&pedPartition->geom, zeroes, 0, 129); - delete[] zeroes; - - if (!rval) - report.line() << xi18nc("@info:progress", "Failed to erase filesystem signature on partition %1.", partition.deviceNode()); - - ped_device_close(pedDevice()); - } - } else - rval = true; - } else - report.line() << xi18nc("@info:progress", "Could not delete file system on partition %1: Failed to get partition.", partition.deviceNode()); - - return rval; -} - -#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT -static void pedTimerHandler(PedTimer* pedTimer, void*) -{ - CoreBackendManager::self()->backend()->emitProgress(pedTimer->frac * 100); -} -#endif - -bool LibPartedPartitionTable::resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) -{ - bool rval = false; - -#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT - if (PedGeometry* originalGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), partition.fileSystem().length())) { - if (PedFileSystem* pedFileSystem = ped_file_system_open(originalGeometry)) { - if (PedGeometry* resizedGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), newLength)) { - PedTimer* pedTimer = ped_timer_new(pedTimerHandler, nullptr); - rval = ped_file_system_resize(pedFileSystem, resizedGeometry, pedTimer); - ped_timer_destroy(pedTimer); - - if (!rval) - report.line() << xi18nc("@info:progress", "Could not resize file system on partition %1.", partition.deviceNode()); - ped_geometry_destroy(resizedGeometry); - } else - report.line() << xi18nc("@info:progress", "Could not get geometry for resized partition %1 while trying to resize the file system.", partition.deviceNode()); - - ped_file_system_close(pedFileSystem); - } else - report.line() << xi18nc("@info:progress", "Could not open partition %1 while trying to resize the file system.", partition.deviceNode()); - ped_geometry_destroy(originalGeometry); - } else - report.line() << xi18nc("@info:progress", "Could not read geometry for partition %1 while trying to resize the file system.", partition.deviceNode()); -#else - Q_UNUSED(report) - Q_UNUSED(partition) - Q_UNUSED(newLength) -#endif - - return rval; -} - -FileSystem::Type LibPartedPartitionTable::detectFileSystemBySector(Report& report, const Device& device, qint64 sector) -{ - PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), sector); - - char* pedPath = ped_partition_get_path(pedPartition); - FileSystem::Type type = FileSystem::Unknown; - if (pedPartition && pedPath) - type = CoreBackendManager::self()->backend()->detectFileSystem(QString::fromLocal8Bit(pedPath)); - else - report.line() << xi18nc("@info:progress", "Could not determine file system of partition at sector %1 on device %2.", sector, device.deviceNode()); - free(pedPath); - - return type; -} - -bool LibPartedPartitionTable::setPartitionSystemType(Report& report, const Partition& partition) -{ - PedFileSystemType* pedFsType = (partition.roles().has(PartitionRole::Extended) || partition.fileSystem().type() == FileSystem::Unformatted) ? nullptr : getPedFileSystemType(partition.fileSystem().type()); - if (pedFsType == nullptr) { - report.line() << xi18nc("@info:progress", "Could not update the system type for partition %1.", partition.deviceNode()); - report.line() << xi18nc("@info:progress", "No file system defined."); - return false; - } - - PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); - if (pedPartition == nullptr) { - report.line() << xi18nc("@info:progress", "Could not update the system type for partition %1.", partition.deviceNode()); - report.line() << xi18nc("@info:progress", "No partition found at sector %1.", partition.firstSector()); - return false; - } - - return ped_partition_set_system(pedPartition, pedFsType) != 0; -} - -bool LibPartedPartitionTable::setFlag(Report& report, const Partition& partition, PartitionTable::Flag flag, bool state) -{ - PedPartition* pedPartition; - if (partition.roles().has(PartitionRole::Extended)) - pedPartition = ped_disk_extended_partition(pedDisk()); - else - pedPartition = ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); - if (pedPartition == nullptr) { - QString deviceNode = QString::fromUtf8(pedDevice()->path); - report.line() << xi18nc("@info:progress", "Could not find partition %1 on device %2 to set partition flags.", partition.deviceNode(), deviceNode); - return false; - } - - const PedPartitionFlag f = LibPartedBackend::getPedFlag(flag); - - // ignore flags that don't exist for this partition - if (!ped_partition_is_flag_available(pedPartition, f)) { - report.line() << xi18nc("@info:progress", "The flag \"%1\" is not available on the partition's partition table.", PartitionTable::flagName(flag)); - return true; - } - - // Workaround: libparted claims the hidden flag is available for extended partitions, but - // throws an error when we try to set or clear it. So skip this combination. - if (pedPartition->type == PED_PARTITION_EXTENDED && flag == PartitionTable::FlagHidden) - return true; - - if (!ped_partition_set_flag(pedPartition, f, state ? 1 : 0)) - return false; - - return true; -} diff --git a/src/plugins/libparted/libpartedpartitiontable.h b/src/plugins/libparted/libpartedpartitiontable.h deleted file mode 100644 index 268d0bb..0000000 --- a/src/plugins/libparted/libpartedpartitiontable.h +++ /dev/null @@ -1,68 +0,0 @@ -/************************************************************************* - * Copyright (C) 2010, 2011 by Volker Lanz * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#if !defined(KPMCORE_LIBPARTEDPARTITIONTABLE_H) - -#define KPMCORE_LIBPARTEDPARTITIONTABLE_H - -#include "backend/corebackendpartitiontable.h" - -#include "fs/filesystem.h" - -#include - -#include - -class CoreBackendPartition; -class Report; -class Partition; - -class LibPartedPartitionTable : public CoreBackendPartitionTable -{ -public: - LibPartedPartitionTable(PedDevice* device); - ~LibPartedPartitionTable(); - -public: - bool open() override; - - bool commit(quint32 timeout = 10) override; - static bool commit(PedDisk* pd, quint32 timeout = 10); - - QString createPartition(Report& report, const Partition& partition) override; - bool deletePartition(Report& report, const Partition& partition) override; - bool updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) override; - bool clobberFileSystem(Report& report, const Partition& partition) override; - bool resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) override; - FileSystem::Type detectFileSystemBySector(Report& report, const Device& device, qint64 sector) override; - bool setPartitionSystemType(Report& report, const Partition& partition) override; - bool setFlag(Report& report, const Partition& partition, PartitionTable::Flag flag, bool state) override; - -private: - PedDevice* pedDevice() { - return m_PedDevice; - } - PedDisk* pedDisk() { - return m_PedDisk; - } - -private: - PedDevice* m_PedDevice; - PedDisk* m_PedDisk; -}; - -#endif diff --git a/src/plugins/libparted/pedflags.h b/src/plugins/libparted/pedflags.h deleted file mode 100644 index 3687a18..0000000 --- a/src/plugins/libparted/pedflags.h +++ /dev/null @@ -1,46 +0,0 @@ -/************************************************************************* - * Copyright (C) 2008, 2010 by Volker Lanz * - * Copyright (C) 2015 by Teo Mrnjavac * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#ifndef KPMCORE_PEDFLAGS_H -#define KPMCORE_PEDFLAGS_H - -static struct { - PedPartitionFlag pedFlag; - PartitionTable::Flag flag; -} flagmap[] = { - { PED_PARTITION_BOOT, PartitionTable::FlagBoot }, - { PED_PARTITION_ROOT, PartitionTable::FlagRoot }, - { PED_PARTITION_SWAP, PartitionTable::FlagSwap }, - { PED_PARTITION_HIDDEN, PartitionTable::FlagHidden }, - { PED_PARTITION_RAID, PartitionTable::FlagRaid }, - { PED_PARTITION_LVM, PartitionTable::FlagLvm }, - { PED_PARTITION_LBA, PartitionTable::FlagLba }, - { PED_PARTITION_HPSERVICE, PartitionTable::FlagHpService }, - { PED_PARTITION_PALO, PartitionTable::FlagPalo }, - { PED_PARTITION_PREP, PartitionTable::FlagPrep }, - { PED_PARTITION_MSFT_RESERVED, PartitionTable::FlagMsftReserved }, - { PED_PARTITION_BIOS_GRUB, PartitionTable::FlagBiosGrub }, - { PED_PARTITION_APPLE_TV_RECOVERY, PartitionTable::FlagAppleTvRecovery }, - { PED_PARTITION_DIAG, PartitionTable::FlagDiag }, // generic diagnostics flag - { PED_PARTITION_LEGACY_BOOT, PartitionTable::FlagLegacyBoot }, - { PED_PARTITION_MSFT_DATA, PartitionTable::FlagMsftData }, - { PED_PARTITION_IRST, PartitionTable::FlagIrst }, // Intel Rapid Start partition - { PED_PARTITION_ESP, PartitionTable::FlagEsp } // EFI system -}; - -#endif diff --git a/src/plugins/libparted/pmlibpartedbackendplugin.json b/src/plugins/libparted/pmlibpartedbackendplugin.json deleted file mode 100644 index 2593eef..0000000 --- a/src/plugins/libparted/pmlibpartedbackendplugin.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "KPlugin": { - "Authors": [ - { - "Email": "vl@fidra.de", - "Name": "Volker Lanz", - "Name[x-test]": "xxVolker Lanzxx" - } - ], - "Category": "BackendPlugin", - "Description": "The LibParted backend for KDE Partition Manager", - "Description[ca@valencia]": "Un dorsal pel LibParted del gestor de particions del KDE", - "Description[ca]": "Un dorsal pel LibParted del gestor de particions del KDE", - "Description[de]": "Das LibParted-Backend für die KDE-Partitionsverwaltung", - "Description[es]": "El motor LibParted para el gestor de particiones de KDE", - "Description[nl]": "De LibParted-backend voor de KDE-partitiebeheerder", - "Description[pt]": "A infra-estrutura da LibParted para o Gestor de Partições do KDE", - "Description[sk]": "LibParted - program v pozadí pre KDE Správcu partícií", - "Description[sv]": "LibParted bakgrundsprogrammet till KDE:s partitionshanterare", - "Description[uk]": "Сервер LibParted для Керування розділами KDE", - "Description[x-test]": "xxThe LibParted backend for KDE Partition Managerxx", - "EnabledByDefault": true, - "Icon": "preferences-plugin", - "Id": "pmlibpartedbackendplugin", - "License": "GPL", - "Name": "KDE Partition Manager LibParted Backend", - "Name[ca@valencia]": "Dorsal pel LibParted del gestor de particions del KDE", - "Name[ca]": "Dorsal pel LibParted del gestor de particions del KDE", - "Name[de]": "KDE-Partitionsverwaltung LibParted-Backend", - "Name[es]": "Motor LibParted para el gestor de particiones de KDE", - "Name[fi]": "KDE:n osionhallinnan LibParted-taustaosa", - "Name[fr]": "Moteur LibParted pour le gestionnaire de partitions de KDE", - "Name[id]": "Backend LibParted Pengelola Parisi KDE", - "Name[it]": "Motore LibParted del gestore delle partizioni di KDE", - "Name[nb]": "KDE partisjonsbehandler, bakgrunnsmotor for libparted", - "Name[nl]": "KDE-partitiebeheerder LibParted-backend", - "Name[pt]": "Infra-Estrutura da LibParted para o Gestor de Partições do KDE", - "Name[sk]": "LibParted - program v pozadí pre KDE Správcu partícií", - "Name[sv]": "KDE:s partitionshanterare LibParted bakgrundsprogram", - "Name[uk]": "Сервер LibParted Керування розділами KDE", - "Name[x-test]": "xxKDE Partition Manager LibParted Backendxx", - "ServiceTypes": [ - "PartitionManager/Plugin" - ], - "Version": "1", - "Website": "http://www.partitionmanager.org" - } -} From 1500eeb62553ddc115c307c741ad1b0deaff130d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 14:44:40 +0100 Subject: [PATCH 063/175] Use std::unique_ptr for CoreBackendDevices --- src/backend/corebackend.h | 12 ++++-------- src/core/copysourcedevice.cpp | 7 ------- src/core/copysourcedevice.h | 6 ++++-- src/core/copytargetdevice.cpp | 7 ------- src/core/copytargetdevice.h | 6 ++++-- src/jobs/createfilesystemjob.cpp | 4 +--- src/jobs/createpartitionjob.cpp | 4 +--- src/jobs/createpartitiontablejob.cpp | 4 +--- src/jobs/deletefilesystemjob.cpp | 3 +-- src/jobs/deletepartitionjob.cpp | 4 +--- src/jobs/resizefilesystemjob.cpp | 5 +++-- src/jobs/restorefilesystemjob.cpp | 2 +- src/jobs/setpartflagsjob.cpp | 4 +--- src/jobs/setpartgeometryjob.cpp | 4 +--- src/plugins/dummy/dummybackend.cpp | 18 +++++++----------- src/plugins/dummy/dummybackend.h | 6 +++--- src/plugins/sfdisk/sfdiskbackend.cpp | 18 +++++++----------- src/plugins/sfdisk/sfdiskbackend.h | 6 +++--- 18 files changed, 43 insertions(+), 77 deletions(-) diff --git a/src/backend/corebackend.h b/src/backend/corebackend.h index 92c1bb8..c2e1153 100644 --- a/src/backend/corebackend.h +++ b/src/backend/corebackend.h @@ -136,25 +136,21 @@ public: * an instance is returned, it's the caller's responsibility to delete the * object. */ - virtual CoreBackendDevice* openDevice(const Device& d) = 0; + virtual std::unique_ptr openDevice(const Device& d) = 0; /** * Open a device in exclusive mode for writing. * @param deviceNode The path of the device that is to be opened (e.g. /dev/sda) - * @return a pointer to a CoreBackendDevice or nullptr if the open failed. If a pointer to - * an instance is returned, it's the caller's responsibility to delete the - * object. + * @return a pointer to a CoreBackendDevice or nullptr if the open failed. */ - virtual CoreBackendDevice* openDeviceExclusive(const Device& d) = 0; + virtual std::unique_ptr openDeviceExclusive(const Device& d) = 0; /** * Close a CoreBackendDevice that has previously been opened. * @param core_device Pointer to the CoreBackendDevice to be closed. Must not be nullptr. * @return true if closing the CoreBackendDevice succeeded, otherwise false. - * - * This method does not delete the object. */ - virtual bool closeDevice(CoreBackendDevice* core_device) = 0; + virtual bool closeDevice(std::unique_ptr coreDevice) = 0; /** * Emit progress. diff --git a/src/core/copysourcedevice.cpp b/src/core/copysourcedevice.cpp index 9754a0d..18fcb85 100644 --- a/src/core/copysourcedevice.cpp +++ b/src/core/copysourcedevice.cpp @@ -20,7 +20,6 @@ #include "backend/corebackend.h" #include "backend/corebackendmanager.h" -#include "backend/corebackenddevice.h" #include "core/copytarget.h" #include "core/copytargetdevice.h" @@ -40,12 +39,6 @@ CopySourceDevice::CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte) { } -/** Destructs a CopySourceDevice */ -CopySourceDevice::~CopySourceDevice() -{ - delete m_BackendDevice; -} - /** Opens the Device @return true if the Device could be successfully opened */ diff --git a/src/core/copysourcedevice.h b/src/core/copysourcedevice.h index bfdbd45..07aee9d 100644 --- a/src/core/copysourcedevice.h +++ b/src/core/copysourcedevice.h @@ -19,9 +19,12 @@ #define KPMCORE_COPYSOURCEDEVICE_H +#include "backend/corebackenddevice.h" #include "core/copysource.h" #include "util/libpartitionmanagerexport.h" +#include + #include class Device; @@ -41,7 +44,6 @@ class CopySourceDevice : public CopySource public: CopySourceDevice(Device& d, qint64 firstbyte, qint64 lastbyte); - ~CopySourceDevice(); public: bool open() override; @@ -68,7 +70,7 @@ protected: Device& m_Device; const qint64 m_FirstByte; const qint64 m_LastByte; - CoreBackendDevice* m_BackendDevice; + std::unique_ptr m_BackendDevice; }; #endif diff --git a/src/core/copytargetdevice.cpp b/src/core/copytargetdevice.cpp index 2ad9a02..b5dd671 100644 --- a/src/core/copytargetdevice.cpp +++ b/src/core/copytargetdevice.cpp @@ -19,7 +19,6 @@ #include "backend/corebackend.h" #include "backend/corebackendmanager.h" -#include "backend/corebackenddevice.h" #include "core/device.h" @@ -37,12 +36,6 @@ CopyTargetDevice::CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte) { } -/** Destructs a CopyTargetDevice */ -CopyTargetDevice::~CopyTargetDevice() -{ - delete m_BackendDevice; -} - /** Opens a CopyTargetDevice for writing to. @return true on success */ diff --git a/src/core/copytargetdevice.h b/src/core/copytargetdevice.h index f7021d2..3306b47 100644 --- a/src/core/copytargetdevice.h +++ b/src/core/copytargetdevice.h @@ -19,9 +19,12 @@ #define KPMCORE_COPYTARGETDEVICE_H +#include "backend/corebackenddevice.h" #include "core/copytarget.h" #include "util/libpartitionmanagerexport.h" +#include + #include class Device; @@ -42,7 +45,6 @@ class CopyTargetDevice : public CopyTarget public: CopyTargetDevice(Device& d, qint64 firstbyte, qint64 lastbyte); - ~CopyTargetDevice(); public: bool open() override; @@ -63,7 +65,7 @@ public: protected: Device& m_Device; - CoreBackendDevice* m_BackendDevice; + std::unique_ptr m_BackendDevice; const qint64 m_FirstByte; const qint64 m_LastByte; }; diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index 8db2b47..ad20db7 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -60,7 +60,7 @@ bool CreateFileSystemJob::run(Report& parent) createResult = partition().fileSystem().create(*report, partition().deviceNode()); if (createResult) { if (device().type() == Device::Disk_Device) { - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -75,8 +75,6 @@ bool CreateFileSystemJob::run(Report& parent) delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Could not open device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); } else if (device().type() == Device::LVM_Device) { diff --git a/src/jobs/createpartitionjob.cpp b/src/jobs/createpartitionjob.cpp index bb2b1b2..dae4bf7 100644 --- a/src/jobs/createpartitionjob.cpp +++ b/src/jobs/createpartitionjob.cpp @@ -51,7 +51,7 @@ bool CreatePartitionJob::run(Report& parent) Report* report = jobStarted(parent); if (device().type() == Device::Disk_Device) { - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -70,8 +70,6 @@ bool CreatePartitionJob::run(Report& parent) delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to create new partition %2.", device().deviceNode(), partition().deviceNode()); - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Could not open device %1 to create new partition %2.", device().deviceNode(), partition().deviceNode()); } else if (device().type() == Device::LVM_Device) { diff --git a/src/jobs/createpartitiontablejob.cpp b/src/jobs/createpartitiontablejob.cpp index 3d2fe0b..8ceb8b9 100644 --- a/src/jobs/createpartitiontablejob.cpp +++ b/src/jobs/createpartitiontablejob.cpp @@ -45,14 +45,12 @@ bool CreatePartitionTableJob::run(Report& parent) Report* report = jobStarted(parent); if (device().type() == Device::Disk_Device) { - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice != nullptr) { Q_ASSERT(device().partitionTable()); rval = backendDevice->createPartitionTable(*report, *device().partitionTable()); - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Creating partition table failed: Could not open device %1.", device().deviceNode()); } else if (device().type() == Device::LVM_Device) { diff --git a/src/jobs/deletefilesystemjob.cpp b/src/jobs/deletefilesystemjob.cpp index da95287..f01a3e3 100644 --- a/src/jobs/deletefilesystemjob.cpp +++ b/src/jobs/deletefilesystemjob.cpp @@ -74,7 +74,7 @@ bool DeleteFileSystemJob::run(Report& parent) return false; } - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -92,7 +92,6 @@ bool DeleteFileSystemJob::run(Report& parent) } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to delete file system on %2.", device().deviceNode(), partition().deviceNode()); - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Could not delete file system signature for partition %1: Failed to open device %2.", partition().deviceNode(), device().deviceNode()); } diff --git a/src/jobs/deletepartitionjob.cpp b/src/jobs/deletepartitionjob.cpp index 5ba7401..293496c 100644 --- a/src/jobs/deletepartitionjob.cpp +++ b/src/jobs/deletepartitionjob.cpp @@ -58,7 +58,7 @@ bool DeletePartitionJob::run(Report& parent) Report* report = jobStarted(parent); if (device().type() == Device::Disk_Device) { - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -75,8 +75,6 @@ bool DeletePartitionJob::run(Report& parent) } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to delete partition %2.", device().deviceNode(), partition().deviceNode()); - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Deleting partition failed: Could not open device %1.", device().deviceNode()); } else if (device().type() == Device::LVM_Device) { diff --git a/src/jobs/resizefilesystemjob.cpp b/src/jobs/resizefilesystemjob.cpp index a3af897..d86108a 100644 --- a/src/jobs/resizefilesystemjob.cpp +++ b/src/jobs/resizefilesystemjob.cpp @@ -31,6 +31,8 @@ #include "util/report.h" #include "util/capacity.h" +#include + #include #include @@ -112,7 +114,7 @@ bool ResizeFileSystemJob::resizeFileSystemBackend(Report& report) { bool rval = false; - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -131,7 +133,6 @@ bool ResizeFileSystemJob::resizeFileSystemBackend(Report& report) } else report.line() << xi18nc("@info:progress", "Could not open partition %1 while trying to resize the file system.", partition().deviceNode()); - delete backendDevice; } else report.line() << xi18nc("@info:progress", "Could not read geometry for partition %1 while trying to resize the file system.", partition().deviceNode()); diff --git a/src/jobs/restorefilesystemjob.cpp b/src/jobs/restorefilesystemjob.cpp index aff8d70..a9265da 100644 --- a/src/jobs/restorefilesystemjob.cpp +++ b/src/jobs/restorefilesystemjob.cpp @@ -80,7 +80,7 @@ bool RestoreFileSystemJob::run(Report& parent) // create a new file system for what was restored with the length of the image file const qint64 newLastSector = targetPartition().firstSector() + copySource.length() - 1; - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(targetDevice()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(targetDevice()); FileSystem::Type t = FileSystem::Unknown; diff --git a/src/jobs/setpartflagsjob.cpp b/src/jobs/setpartflagsjob.cpp index 2aad649..33a3070 100644 --- a/src/jobs/setpartflagsjob.cpp +++ b/src/jobs/setpartflagsjob.cpp @@ -56,7 +56,7 @@ bool SetPartFlagsJob::run(Report& parent) Report* report = jobStarted(parent); - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -85,8 +85,6 @@ bool SetPartFlagsJob::run(Report& parent) delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set partition flags for partition %2.", device().deviceNode(), partition().deviceNode()); - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Could not open device %1 to set partition flags for partition %2.", device().deviceNode(), partition().deviceNode()); diff --git a/src/jobs/setpartgeometryjob.cpp b/src/jobs/setpartgeometryjob.cpp index 7a4fbd7..9c3a488 100644 --- a/src/jobs/setpartgeometryjob.cpp +++ b/src/jobs/setpartgeometryjob.cpp @@ -56,7 +56,7 @@ bool SetPartGeometryJob::run(Report& parent) Report* report = jobStarted(parent); if(device().type() == Device::Disk_Device) { - CoreBackendDevice* backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); @@ -72,8 +72,6 @@ bool SetPartGeometryJob::run(Report& parent) delete backendPartitionTable; } - - delete backendDevice; } else report->line() << xi18nc("@info:progress", "Could not open device %1 while trying to resize/move partition %2.", device().deviceNode(), partition().deviceNode()); } else if (device().type() == Device::LVM_Device) { diff --git a/src/plugins/dummy/dummybackend.cpp b/src/plugins/dummy/dummybackend.cpp index 5abc6f2..30fe534 100644 --- a/src/plugins/dummy/dummybackend.cpp +++ b/src/plugins/dummy/dummybackend.cpp @@ -91,31 +91,27 @@ QString DummyBackend::readUUID(const QString& deviceNode) const return QString(); } -CoreBackendDevice* DummyBackend::openDevice(const Device& d) +std::unique_ptr DummyBackend::openDevice(const Device& d) { - DummyDevice* device = new DummyDevice(d.deviceNode()); + std::unique_ptr device = std::make_unique(d.deviceNode()); - if (device == nullptr || !device->open()) { - delete device; + if (!device->open()) device = nullptr; - } return device; } -CoreBackendDevice* DummyBackend::openDeviceExclusive(const Device& d) +std::unique_ptr DummyBackend::openDeviceExclusive(const Device& d) { - DummyDevice* device = new DummyDevice(d.deviceNode()); + std::unique_ptr device = std::make_unique(d.deviceNode()); - if (device == nullptr || !device->openExclusive()) { - delete device; + if (!device->openExclusive()) device = nullptr; - } return device; } -bool DummyBackend::closeDevice(CoreBackendDevice* coreDevice) +bool DummyBackend::closeDevice(std::unique_ptr coreDevice) { return coreDevice->close(); } diff --git a/src/plugins/dummy/dummybackend.h b/src/plugins/dummy/dummybackend.h index 12aad6b..a9f8fb3 100644 --- a/src/plugins/dummy/dummybackend.h +++ b/src/plugins/dummy/dummybackend.h @@ -45,9 +45,9 @@ public: void initFSSupport() override; QList scanDevices(bool excludeReadOnly = false) override; - CoreBackendDevice* openDevice(const Device& d) override; - CoreBackendDevice* openDeviceExclusive(const Device& d) override; - bool closeDevice(CoreBackendDevice* coreDevice) override; + std::unique_ptr openDevice(const Device& d) override; + std::unique_ptr openDeviceExclusive(const Device& d) override; + bool closeDevice(std::unique_ptr coreDevice) override; Device* scanDevice(const QString& deviceNode) override; FileSystem::Type detectFileSystem(const QString& deviceNode) override; QString readLabel(const QString& deviceNode) const override; diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 57a510d..aa103b7 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -403,31 +403,27 @@ PartitionTable::Flags SfdiskBackend::availableFlags(PartitionTable::TableType ty return flags; } -CoreBackendDevice* SfdiskBackend::openDevice(const Device& d) +std::unique_ptr SfdiskBackend::openDevice(const Device& d) { - SfdiskDevice* device = new SfdiskDevice(d); + std::unique_ptr device = std::make_unique(d); - if (device == nullptr || !device->open()) { - delete device; + if (!device->open()) device = nullptr; - } return device; } -CoreBackendDevice* SfdiskBackend::openDeviceExclusive(const Device& d) +std::unique_ptr SfdiskBackend::openDeviceExclusive(const Device& d) { - SfdiskDevice* device = new SfdiskDevice(d); + std::unique_ptr device = std::make_unique(d); - if (device == nullptr || !device->openExclusive()) { - delete device; + if (!device->openExclusive()) device = nullptr; - } return device; } -bool SfdiskBackend::closeDevice(CoreBackendDevice* coreDevice) +bool SfdiskBackend::closeDevice(std::unique_ptr coreDevice) { return coreDevice->close(); } diff --git a/src/plugins/sfdisk/sfdiskbackend.h b/src/plugins/sfdisk/sfdiskbackend.h index 5cb3291..d60deb1 100644 --- a/src/plugins/sfdisk/sfdiskbackend.h +++ b/src/plugins/sfdisk/sfdiskbackend.h @@ -47,9 +47,9 @@ public: void initFSSupport() override; QList scanDevices(bool excludeReadOnly = false) override; - CoreBackendDevice* openDevice(const Device& d) override; - CoreBackendDevice* openDeviceExclusive(const Device& d) override; - bool closeDevice(CoreBackendDevice* coreDevice) override; + std::unique_ptr openDevice(const Device& d) override; + std::unique_ptr openDeviceExclusive(const Device& d) override; + bool closeDevice(std::unique_ptr coreDevice) override; Device* scanDevice(const QString& deviceNode) override; FileSystem::Type detectFileSystem(const QString& partitionPath) override; QString readLabel(const QString& deviceNode) const override; From 738842799a84dbf1f4c5c1185818a469d5237c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 16:30:53 +0100 Subject: [PATCH 064/175] Make kpmcore link libraries private. --- src/CMakeLists.txt | 7 ++++--- src/fs/filesystem.cpp | 1 + src/fs/filesystem.h | 2 +- src/fs/luks.cpp | 1 + src/fs/luks.h | 2 +- src/plugins/dummy/CMakeLists.txt | 2 +- src/plugins/sfdisk/CMakeLists.txt | 2 +- src/util/externalcommand.cpp | 1 + src/util/externalcommand.h | 3 +-- test/CMakeLists.txt | 2 +- test/testexternalcommand.cpp | 4 ++-- 11 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00b1b91..156c7cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,13 +40,14 @@ ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES}) add_library(kpmcore SHARED ${kpmcore_SRCS}) target_link_libraries( kpmcore PUBLIC - ${UUID_LIBRARIES} - ${BLKID_LIBRARIES} + PRIVATE + Qt5::Core Qt5::DBus + Qt5::Gui KF5::I18n KF5::CoreAddons KF5::WidgetsAddons - PRIVATE + ${BLKID_LIBRARIES} KF5::Auth ) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index fa4e640..b0e9f04 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -31,6 +31,7 @@ #include +#include #include #include #include diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 27451a7..244c83c 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -22,7 +22,6 @@ #include "util/libpartitionmanagerexport.h" -#include #include #include #include @@ -31,6 +30,7 @@ #include +class QColor; class QValidator; class Device; class Report; diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index 1554523..b82f64f 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/fs/luks.h b/src/fs/luks.h index 9ee8ea4..bbcab61 100644 --- a/src/fs/luks.h +++ b/src/fs/luks.h @@ -26,11 +26,11 @@ #include "fs/filesystem.h" #include -#include class Report; class QString; +class QWidget; namespace FS { diff --git a/src/plugins/dummy/CMakeLists.txt b/src/plugins/dummy/CMakeLists.txt index f5b2a26..1c04df4 100644 --- a/src/plugins/dummy/CMakeLists.txt +++ b/src/plugins/dummy/CMakeLists.txt @@ -22,6 +22,6 @@ set (pmdummybackendplugin_SRCS add_library(pmdummybackendplugin SHARED ${pmdummybackendplugin_SRCS}) -target_link_libraries(pmdummybackendplugin kpmcore) +target_link_libraries(pmdummybackendplugin kpmcore KF5::I18n KF5::CoreAddons) install(TARGETS pmdummybackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR}) diff --git a/src/plugins/sfdisk/CMakeLists.txt b/src/plugins/sfdisk/CMakeLists.txt index 6b7df1a..d910c3f 100644 --- a/src/plugins/sfdisk/CMakeLists.txt +++ b/src/plugins/sfdisk/CMakeLists.txt @@ -22,6 +22,6 @@ set (pmsfdiskbackendplugin_SRCS add_library(pmsfdiskbackendplugin SHARED ${pmsfdiskbackendplugin_SRCS}) -target_link_libraries(pmsfdiskbackendplugin kpmcore) +target_link_libraries(pmsfdiskbackendplugin kpmcore KF5::I18n KF5::CoreAddons) install(TARGETS pmsfdiskbackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR}) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 9f7cd74..02f60b8 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -37,6 +37,7 @@ #include #include +#include #include /** Creates a new ExternalCommand instance without Report. diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index cf9e41e..43b151c 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -24,8 +24,6 @@ #include "core/copysourcedevice.h" #include "core/copytargetfile.h" -#include - #include #include #include @@ -33,6 +31,7 @@ #include #include +class KJob; class Report; /** An external command. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f08c9af..67f63a2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,7 +20,7 @@ target_link_libraries(testhelpers) macro (kpm_test name) add_executable(${name} ${ARGN}) - target_link_libraries(${name} testhelpers kpmcore) + target_link_libraries(${name} testhelpers kpmcore Qt5::Core) endmacro() ### diff --git a/test/testexternalcommand.cpp b/test/testexternalcommand.cpp index 5dbabac..aec3d31 100644 --- a/test/testexternalcommand.cpp +++ b/test/testexternalcommand.cpp @@ -22,7 +22,7 @@ #include "backend/corebackendmanager.h" #include "util/externalcommand.h" -#include +#include #include #include @@ -52,7 +52,7 @@ void run() int main( int argc, char **argv ) { - QApplication app(argc, argv); + QCoreApplication app(argc, argv); KPMCoreInitializer i(QStringLiteral("pmsfdiskbackendplugin")); runcmd a; From 1062766e3654d22e2eea103014c38d6ea5b91f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 16:44:00 +0100 Subject: [PATCH 065/175] Fix spelling mistake. --- test/helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers.h b/test/helpers.h index eae46b0..44f4cd7 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -23,7 +23,7 @@ class QString; /** - * Use RAII to initialize the KPMcore library. Just instantiatie one + * Use RAII to initialize the KPMcore library. Just instantiate one * object of this class to do "normal" initialization. */ class KPMCoreInitializer From 5e85f0b9748496aa0f969c2e530f024a42066fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 18:01:00 +0100 Subject: [PATCH 066/175] Remove ping interface in KAuth helper as it is blocking KPM GUI. --- src/backend/corebackendmanager.cpp | 17 ----------------- src/util/externalcommandhelper.cpp | 12 ------------ src/util/externalcommandhelper.h | 1 - 3 files changed, 30 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index d961404..db60de9 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -86,22 +85,6 @@ void CoreBackendManager::startExternalCommandHelper() QObject::connect(job(), &KJob::finished, [=] () { if(d->m_job->error()) exitLoop(); } ); loop.exec(); QObject::disconnect(conn); - - // Watchdog Timer for the DBus service - QTimer *timer = new QTimer; - - auto sendDBusPing = [&] () { - QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), - QStringLiteral("/Helper"), - QStringLiteral("org.kde.kpmcore.externalcommand"), - QDBusConnection::systemBus()); - - if (iface.isValid()) - iface.call(QStringLiteral("ping"), CoreBackendManager::self()->Uuid()); - }; - - QObject::connect(timer, &QTimer::timeout, sendDBusPing); - timer->start(20000); // 20 seconds } void CoreBackendManager::stopExternalCommandHelper() diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 4591307..0601f23 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -48,10 +48,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); - timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, [=] () { exit(m_callerUuid); }); - timer->start(TIMEOUT); - HelperSupport::progressStep(QVariantMap()); m_loop.exec(); reply.addData(QStringLiteral("success"), true); @@ -244,14 +240,6 @@ void ExternalCommandHelper::exit(const QString& Uuid) QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper")); } -void ExternalCommandHelper::ping(const QString &Uuid) -{ - if (!isCallerAuthorized(Uuid)) - return; - - timer->setInterval(TIMEOUT); -} - void ExternalCommandHelper::onReadOutput() { // const QByteArray s = cmd.readAllStandardOutput(); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index aba456a..299a27e 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -46,7 +46,6 @@ public Q_SLOTS: Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); - Q_SCRIPTABLE void ping(const QString& Uuid); private: void onReadOutput(); From 279159ca6f65eac74e78356097ba194bc9aa9341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 21:49:20 +0100 Subject: [PATCH 067/175] Use smart pointers for CoreBackendPartitionTable. --- src/backend/corebackend.h | 4 +--- src/backend/corebackenddevice.h | 3 ++- src/backend/corebackendmanager.cpp | 9 ++++++++- src/backend/corebackendmanager_p.h | 30 ----------------------------- src/jobs/createfilesystemjob.cpp | 4 +--- src/jobs/createpartitionjob.cpp | 4 +--- src/jobs/deletefilesystemjob.cpp | 5 +---- src/jobs/deletepartitionjob.cpp | 5 +---- src/jobs/resizefilesystemjob.cpp | 4 +--- src/jobs/restorefilesystemjob.cpp | 2 +- src/jobs/setpartflagsjob.cpp | 4 +--- src/jobs/setpartgeometryjob.cpp | 4 +--- src/plugins/dummy/dummydevice.cpp | 11 ++--------- src/plugins/dummy/dummydevice.h | 2 +- src/plugins/sfdisk/sfdiskdevice.cpp | 4 ++-- src/plugins/sfdisk/sfdiskdevice.h | 2 +- 16 files changed, 25 insertions(+), 72 deletions(-) delete mode 100644 src/backend/corebackendmanager_p.h diff --git a/src/backend/corebackend.h b/src/backend/corebackend.h index c2e1153..e44b740 100644 --- a/src/backend/corebackend.h +++ b/src/backend/corebackend.h @@ -132,9 +132,7 @@ public: /** * Open a device for reading. * @param deviceNode The path of the device that is to be opened (e.g. /dev/sda) - * @return a pointer to a CoreBackendDevice or nullptr if the open failed. If a pointer to - * an instance is returned, it's the caller's responsibility to delete the - * object. + * @return a pointer to a CoreBackendDevice or nullptr if the open failed. */ virtual std::unique_ptr openDevice(const Device& d) = 0; diff --git a/src/backend/corebackenddevice.h b/src/backend/corebackenddevice.h index b3c3126..0629f33 100644 --- a/src/backend/corebackenddevice.h +++ b/src/backend/corebackenddevice.h @@ -19,6 +19,7 @@ #define KPMCORE_COREBACKENDDEVICE_H +#include #include class CoreBackendPartition; @@ -81,7 +82,7 @@ public: * @return a pointer to the CoreBackendPartitionTable for this device or nullptr in case * of errors */ - virtual CoreBackendPartitionTable* openPartitionTable() = 0; + virtual std::unique_ptr openPartitionTable() = 0; /** * Create a new partition table on this device. diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index db60de9..1fbca68 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -18,7 +18,6 @@ *************************************************************************/ #include "backend/corebackendmanager.h" -#include "backend/corebackendmanager_p.h" #include "backend/corebackend.h" #include @@ -35,6 +34,14 @@ #include #include +struct CoreBackendManagerPrivate +{ + KAuth::ExecuteJob *m_job; + CoreBackend *m_Backend; + + QString m_Uuid; +}; + CoreBackendManager::CoreBackendManager() : d(std::make_unique()) { diff --git a/src/backend/corebackendmanager_p.h b/src/backend/corebackendmanager_p.h deleted file mode 100644 index d28bcb4..0000000 --- a/src/backend/corebackendmanager_p.h +++ /dev/null @@ -1,30 +0,0 @@ -/************************************************************************* - * Copyright (C) 2018 by Andrius Štikonas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 3 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see .* - *************************************************************************/ - -#ifndef KPMCORE_COREBACKENDMANAGER_P_H - -#define KPMCORE_COREBACKENDMANAGER_P_H - -struct CoreBackendManagerPrivate -{ - KAuth::ExecuteJob *m_job; - CoreBackend *m_Backend; - - QString m_Uuid; -}; - -#endif diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index ad20db7..09e63a2 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -63,7 +63,7 @@ bool CreateFileSystemJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { if (backendPartitionTable->setPartitionSystemType(*report, partition())) { @@ -71,8 +71,6 @@ bool CreateFileSystemJob::run(Report& parent) backendPartitionTable->commit(); } else report->line() << xi18nc("@info:progress", "Failed to set the system type for the file system on partition %1.", partition().deviceNode()); - - delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); } else diff --git a/src/jobs/createpartitionjob.cpp b/src/jobs/createpartitionjob.cpp index dae4bf7..a67a132 100644 --- a/src/jobs/createpartitionjob.cpp +++ b/src/jobs/createpartitionjob.cpp @@ -54,7 +54,7 @@ bool CreatePartitionJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { QString partitionPath = backendPartitionTable->createPartition(*report, partition()); @@ -66,8 +66,6 @@ bool CreatePartitionJob::run(Report& parent) backendPartitionTable->commit(); } else report->line() << xi18nc("@info/plain", "Failed to add partition %1 to device %2.", partition().deviceNode(), device().deviceNode()); - - delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to create new partition %2.", device().deviceNode(), partition().deviceNode()); } else diff --git a/src/jobs/deletefilesystemjob.cpp b/src/jobs/deletefilesystemjob.cpp index f01a3e3..6ff797e 100644 --- a/src/jobs/deletefilesystemjob.cpp +++ b/src/jobs/deletefilesystemjob.cpp @@ -77,7 +77,7 @@ bool DeleteFileSystemJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { rval = backendPartitionTable->clobberFileSystem(*report, partition()); @@ -86,9 +86,6 @@ bool DeleteFileSystemJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not delete file system on %1.", partition().deviceNode()); else backendPartitionTable->commit(); - - delete backendPartitionTable; - } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to delete file system on %2.", device().deviceNode(), partition().deviceNode()); diff --git a/src/jobs/deletepartitionjob.cpp b/src/jobs/deletepartitionjob.cpp index 293496c..20bada2 100644 --- a/src/jobs/deletepartitionjob.cpp +++ b/src/jobs/deletepartitionjob.cpp @@ -61,7 +61,7 @@ bool DeletePartitionJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { rval = backendPartitionTable->deletePartition(*report, partition()); @@ -70,9 +70,6 @@ bool DeletePartitionJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not delete partition %1.", partition().deviceNode()); else backendPartitionTable->commit(); - - delete backendPartitionTable; - } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to delete partition %2.", device().deviceNode(), partition().deviceNode()); } else diff --git a/src/jobs/resizefilesystemjob.cpp b/src/jobs/resizefilesystemjob.cpp index d86108a..f27bd70 100644 --- a/src/jobs/resizefilesystemjob.cpp +++ b/src/jobs/resizefilesystemjob.cpp @@ -117,7 +117,7 @@ bool ResizeFileSystemJob::resizeFileSystemBackend(Report& report) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { connect(CoreBackendManager::self()->backend(), &CoreBackend::progress, this, &ResizeFileSystemJob::progress); @@ -128,8 +128,6 @@ bool ResizeFileSystemJob::resizeFileSystemBackend(Report& report) report.line() << xi18nc("@info:progress", "Successfully resized file system using internal backend functions."); backendPartitionTable->commit(); } - - delete backendPartitionTable; } else report.line() << xi18nc("@info:progress", "Could not open partition %1 while trying to resize the file system.", partition().deviceNode()); diff --git a/src/jobs/restorefilesystemjob.cpp b/src/jobs/restorefilesystemjob.cpp index a9265da..fc62906 100644 --- a/src/jobs/restorefilesystemjob.cpp +++ b/src/jobs/restorefilesystemjob.cpp @@ -85,7 +85,7 @@ bool RestoreFileSystemJob::run(Report& parent) FileSystem::Type t = FileSystem::Unknown; if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) t = backendPartitionTable->detectFileSystemBySector(*report, targetDevice(), targetPartition().firstSector()); diff --git a/src/jobs/setpartflagsjob.cpp b/src/jobs/setpartflagsjob.cpp index 33a3070..fceb583 100644 --- a/src/jobs/setpartflagsjob.cpp +++ b/src/jobs/setpartflagsjob.cpp @@ -59,7 +59,7 @@ bool SetPartFlagsJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { int count = 0; @@ -81,8 +81,6 @@ bool SetPartFlagsJob::run(Report& parent) if (rval) backendPartitionTable->commit(); - - delete backendPartitionTable; } else report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set partition flags for partition %2.", device().deviceNode(), partition().deviceNode()); } else diff --git a/src/jobs/setpartgeometryjob.cpp b/src/jobs/setpartgeometryjob.cpp index 9c3a488..153c352 100644 --- a/src/jobs/setpartgeometryjob.cpp +++ b/src/jobs/setpartgeometryjob.cpp @@ -59,7 +59,7 @@ bool SetPartGeometryJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { - CoreBackendPartitionTable* backendPartitionTable = backendDevice->openPartitionTable(); + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { rval = backendPartitionTable->updateGeometry(*report, partition(), newStart(), newStart() + newLength() - 1); @@ -69,8 +69,6 @@ bool SetPartGeometryJob::run(Report& parent) partition().setLastSector(newStart() + newLength() - 1); backendPartitionTable->commit(); } - - delete backendPartitionTable; } } else report->line() << xi18nc("@info:progress", "Could not open device %1 while trying to resize/move partition %2.", device().deviceNode(), partition().deviceNode()); diff --git a/src/plugins/dummy/dummydevice.cpp b/src/plugins/dummy/dummydevice.cpp index d2b43e9..0ffa283 100644 --- a/src/plugins/dummy/dummydevice.cpp +++ b/src/plugins/dummy/dummydevice.cpp @@ -47,16 +47,9 @@ bool DummyDevice::close() return true; } -CoreBackendPartitionTable* DummyDevice::openPartitionTable() +std::unique_ptr DummyDevice::openPartitionTable() { - CoreBackendPartitionTable* ptable = new DummyPartitionTable(); - - if (ptable == nullptr || !ptable->open()) { - delete ptable; - ptable = nullptr; - } - - return ptable; + return std::make_unique(DummyPartitionTable()); } bool DummyDevice::createPartitionTable(Report& report, const PartitionTable& ptable) diff --git a/src/plugins/dummy/dummydevice.h b/src/plugins/dummy/dummydevice.h index 6895e65..746c346 100644 --- a/src/plugins/dummy/dummydevice.h +++ b/src/plugins/dummy/dummydevice.h @@ -41,7 +41,7 @@ public: bool openExclusive() override; bool close() override; - CoreBackendPartitionTable* openPartitionTable() override; + std::unique_ptr openPartitionTable() override; bool createPartitionTable(Report& report, const PartitionTable& ptable) override; }; diff --git a/src/plugins/sfdisk/sfdiskdevice.cpp b/src/plugins/sfdisk/sfdiskdevice.cpp index 7dfc248..d8e1887 100644 --- a/src/plugins/sfdisk/sfdiskdevice.cpp +++ b/src/plugins/sfdisk/sfdiskdevice.cpp @@ -58,9 +58,9 @@ bool SfdiskDevice::close() return true; } -CoreBackendPartitionTable* SfdiskDevice::openPartitionTable() +std::unique_ptr SfdiskDevice::openPartitionTable() { - return new SfdiskPartitionTable(m_device); + return std::make_unique(m_device); } bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& ptable) diff --git a/src/plugins/sfdisk/sfdiskdevice.h b/src/plugins/sfdisk/sfdiskdevice.h index 096dd74..eab4a12 100644 --- a/src/plugins/sfdisk/sfdiskdevice.h +++ b/src/plugins/sfdisk/sfdiskdevice.h @@ -42,7 +42,7 @@ public: bool openExclusive() override; bool close() override; - CoreBackendPartitionTable* openPartitionTable() override; + std::unique_ptr openPartitionTable() override; bool createPartitionTable(Report& report, const PartitionTable& ptable) override; From a83cb256cb6890588ad0e35da40dbe9d76a411cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 22:08:55 +0100 Subject: [PATCH 068/175] Finish d-pointerizing CoreBackend class. --- src/backend/corebackend.cpp | 20 +++++++++++++++++--- src/backend/corebackend.h | 20 +++++--------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/backend/corebackend.cpp b/src/backend/corebackend.cpp index 9c1d42e..380ffe1 100644 --- a/src/backend/corebackend.cpp +++ b/src/backend/corebackend.cpp @@ -24,10 +24,9 @@ #include -class CoreBackend::CoreBackendPrivate +struct CoreBackendPrivate { -public: - CoreBackendPrivate() {} + QString m_id, m_version; }; CoreBackend::CoreBackend() : @@ -58,3 +57,18 @@ void CoreBackend::setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_pr { p.setMaxPrimaries(max_primaries); } + +QString CoreBackend::id() { + return d->m_id; +} + +QString CoreBackend::version() { + return d->m_version; +} + +void CoreBackend::setId(const QString& id) { + d->m_id = id; +} +void CoreBackend::setVersion(const QString& version) { + d->m_version = version; +} diff --git a/src/backend/corebackend.h b/src/backend/corebackend.h index e44b740..6a61b34 100644 --- a/src/backend/corebackend.h +++ b/src/backend/corebackend.h @@ -30,6 +30,7 @@ class CoreBackendManager; class CoreBackendDevice; +class CoreBackendPrivate; class Device; class PartitionTable; @@ -70,17 +71,13 @@ public: * Return the plugin's unique Id from JSON metadata * @return the plugin's unique Id from JSON metadata */ - QString id() { - return m_id; - } + QString id(); /** * Return the plugin's version from JSON metadata * @return the plugin's version from JSON metadata */ - QString version() { - return m_version; - } + QString version(); /** * Initialize the plugin's FileSystem support @@ -172,17 +169,10 @@ protected: static void setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_primaries); private: - void setId(const QString& id) { - m_id = id; - } - void setVersion(const QString& version) { - m_version = version; - } + void setId(const QString& id); + void setVersion(const QString& version); private: - QString m_id, m_version; - - class CoreBackendPrivate; std::unique_ptr d; }; From 7ed6657e30a742e2aad8a6e49cbd8aa3d8bbcc42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 31 Mar 2018 23:49:37 +0100 Subject: [PATCH 069/175] Restore functionality of FileSystem::findExternal This also fixes unused variable warnings --- src/backend/corebackend.cpp | 1 + src/fs/filesystem.cpp | 13 ++++++++----- src/ops/backupoperation.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/corebackend.cpp b/src/backend/corebackend.cpp index 380ffe1..5360610 100644 --- a/src/backend/corebackend.cpp +++ b/src/backend/corebackend.cpp @@ -69,6 +69,7 @@ QString CoreBackend::version() { void CoreBackend::setId(const QString& id) { d->m_id = id; } + void CoreBackend::setVersion(const QString& version) { d->m_version = version; } diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index b0e9f04..f540145 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -531,14 +531,17 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode) return false; } -// FIXME: args and expectedCode is now unused. bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode) { - QString cmd = QStandardPaths::findExecutable(cmdName); - if (cmd.isEmpty()) - cmd = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); + QString cmdFullPath = QStandardPaths::findExecutable(cmdName); + if (cmdFullPath.isEmpty()) + cmdFullPath = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); - return !cmd.isEmpty(); + ExternalCommand cmd(cmdFullPath, args); + if (!cmd.run()) + return false; + + return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode; } bool FileSystem::supportToolFound() const diff --git a/src/ops/backupoperation.h b/src/ops/backupoperation.h index 9f3002d..21fd3f8 100644 --- a/src/ops/backupoperation.h +++ b/src/ops/backupoperation.h @@ -61,6 +61,7 @@ protected: Device& targetDevice() { return m_TargetDevice; } + const Device& targetDevice() const { return m_TargetDevice; } From 398e9c3df597b0a84e714ba381233e17d11e71e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 1 Apr 2018 18:46:26 +0100 Subject: [PATCH 070/175] d-pointerize FstabEntry class --- src/CMakeLists.txt | 2 +- src/backend/corebackend.cpp | 12 ++- src/backend/corebackendmanager.cpp | 9 ++- src/core/fstab.cpp | 125 +++++++++++++++++++++++------ src/core/fstab.h | 125 +++++++++++++++++------------ 5 files changed, 191 insertions(+), 82 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 156c7cd..52ee0b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,8 +40,8 @@ ki18n_wrap_ui(kpmcore_SRCS ${gui_UIFILES}) add_library(kpmcore SHARED ${kpmcore_SRCS}) target_link_libraries( kpmcore PUBLIC - PRIVATE Qt5::Core + PRIVATE Qt5::DBus Qt5::Gui KF5::I18n diff --git a/src/backend/corebackend.cpp b/src/backend/corebackend.cpp index 5360610..fbd3410 100644 --- a/src/backend/corebackend.cpp +++ b/src/backend/corebackend.cpp @@ -58,18 +58,22 @@ void CoreBackend::setPartitionTableMaxPrimaries(PartitionTable& p, qint32 max_pr p.setMaxPrimaries(max_primaries); } -QString CoreBackend::id() { +QString CoreBackend::id() +{ return d->m_id; } -QString CoreBackend::version() { +QString CoreBackend::version() +{ return d->m_version; } -void CoreBackend::setId(const QString& id) { +void CoreBackend::setId(const QString& id) +{ d->m_id = id; } -void CoreBackend::setVersion(const QString& version) { +void CoreBackend::setVersion(const QString& version) +{ d->m_version = version; } diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 1fbca68..62322f2 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -58,7 +58,8 @@ CoreBackendManager* CoreBackendManager::self() return instance; } -CoreBackend* CoreBackendManager::backend() { +CoreBackend* CoreBackendManager::backend() +{ return d->m_Backend; } @@ -101,11 +102,13 @@ void CoreBackendManager::stopExternalCommandHelper() iface.call(QStringLiteral("exit"), CoreBackendManager::self()->Uuid()); } -KAuth::ExecuteJob* CoreBackendManager::job() { +KAuth::ExecuteJob* CoreBackendManager::job() +{ return d->m_job; } -QString& CoreBackendManager::Uuid() { +QString& CoreBackendManager::Uuid() +{ return d->m_Uuid; } diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index ebbad89..4cf9ee4 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -34,25 +34,31 @@ static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode); static QString findBlkIdDevice(const char *token, const QString& value); -FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) - : m_fsSpec(fsSpec) - , m_mountPoint(mountPoint) - , m_type(type) - , m_dumpFreq(dumpFreq) - , m_passNumber(passNumber) - , m_comment(comment) +struct FstabEntryPrivate { - m_options = options.split(QLatin1Char(',')); - parseFsSpec(m_fsSpec, m_entryType, m_deviceNode); -} + QString m_fsSpec; + QString m_deviceNode; + QString m_mountPoint; + QString m_type; + QStringList m_options; + int m_dumpFreq; + int m_passNumber; + QString m_comment; + FstabEntryType m_entryType; +}; -/** - @param s the new value for the fs_spec field of fstab entry -*/ -void FstabEntry::setFsSpec(const QString& s) +FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) : + d(std::make_unique()) { - m_fsSpec = s; - parseFsSpec(m_fsSpec, m_entryType, m_deviceNode); + d->m_fsSpec = fsSpec; + d->m_mountPoint = mountPoint; + d->m_type = type; + d->m_dumpFreq = dumpFreq; + d->m_passNumber = passNumber; + d->m_comment = comment; + + d->m_options = options.split(QLatin1Char(',')); + parseFsSpec(d->m_fsSpec, d->m_entryType, d->m_deviceNode); } FstabEntryList readFstabEntries( const QString& fstabPath ) @@ -66,7 +72,7 @@ FstabEntryList readFstabEntries( const QString& fstabPath ) { QString line = rawLine.trimmed(); if ( line.startsWith( QLatin1Char('#') ) || line.isEmpty()) { - fstabEntries.append( { {}, {}, {}, {}, {}, {}, line } ); + fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, line } ); continue; } @@ -83,27 +89,98 @@ FstabEntryList readFstabEntries( const QString& fstabPath ) // (#) comment (optional). switch (splitLine.length()) { case 4: - fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3) } ); + fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3) } ); break; case 5: - fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt() } ); + fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt() } ); break; case 6: - fstabEntries.append( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt(), splitLine.at(5).toInt(), comment.isEmpty() ? QString() : QLatin1Char('#') + comment } ); + fstabEntries.push_back( {splitLine.at(0), splitLine.at(1), splitLine.at(2), splitLine.at(3), splitLine.at(4).toInt(), splitLine.at(5).toInt(), comment.isEmpty() ? QString() : QLatin1Char('#') + comment } ); break; default: - fstabEntries.append( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } ); + fstabEntries.push_back( { {}, {}, {}, {}, {}, {}, QLatin1Char('#') + line } ); } } fstabFile.close(); - if (fstabEntries.last().entryType() == comment && fstabEntries.last().comment().isEmpty()) - fstabEntries.removeLast(); + if (fstabEntries.back().entryType() == comment && fstabEntries.back().comment().isEmpty()) + fstabEntries.pop_back(); } return fstabEntries; } +void FstabEntry::setFsSpec(const QString& s) +{ + d->m_fsSpec = s; + parseFsSpec(d->m_fsSpec, d->m_entryType, d->m_deviceNode); +} + +const QString& FstabEntry::fsSpec() const +{ + return d->m_fsSpec; +} + +const QString& FstabEntry::deviceNode() const +{ + return d->m_deviceNode; +} + +const QString& FstabEntry::mountPoint() const +{ + return d->m_mountPoint; +} + +const QString& FstabEntry::type() const +{ + return d->m_type; +} + +const QStringList& FstabEntry::options() const +{ + return d->m_options; +} + +int FstabEntry::dumpFreq() const +{ + return d->m_dumpFreq; +} + +int FstabEntry::passNumber() const +{ + return d->m_passNumber; +} + +const QString& FstabEntry::comment() const +{ + return d->m_comment; +} + +FstabEntryType FstabEntry::entryType() const +{ + return d->m_entryType; +} + +void FstabEntry::setMountPoint(const QString& s) +{ + d->m_mountPoint = s; +} + +void FstabEntry::setOptions(const QStringList& s) +{ + d->m_options = s; +} + +void FstabEntry::setDumpFreq(int s) +{ + d->m_dumpFreq = s; +} + +void FstabEntry::setPassNumber(int s) +{ + d->m_passNumber = s; +} + QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath) { QStringList mountPoints; @@ -177,7 +254,7 @@ static void writeEntry(QFile& output, const FstabEntry& entry) << entry.comment() << "\n"; } -bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename) +bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename) { QTemporaryFile out; out.setAutoRemove(false); diff --git a/src/core/fstab.h b/src/core/fstab.h index b813c64..ca3c8b6 100644 --- a/src/core/fstab.h +++ b/src/core/fstab.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2017 by Andrius Štikonas * + * Copyright (C) 2017-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -20,9 +20,13 @@ #include "util/libpartitionmanagerexport.h" +#include + #include #include +struct FstabEntryPrivate; + enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment }; /** Base class for fstab handling. @@ -37,63 +41,84 @@ class LIBKPMCORE_EXPORT FstabEntry public: FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq = 0, int passNumber = 0, const QString& comment = QString()); - const QString& fsSpec() const { - return m_fsSpec; /**< @return the fs_spec field of fstab entry */ - } - const QString& deviceNode() const { - return m_deviceNode; /**< @return the device node corresponding to fs_spec entry */ - } - const QString& mountPoint() const { - return m_mountPoint; /**< @return the mount point (target) for the file system */ - } - const QString& type() const { - return m_type; /**< @return the type of the file system */ - } - const QStringList& options() const { - return m_options; /**< @return the mount options associated with the file system */ - } - int dumpFreq() const { - return m_dumpFreq; /**< @return the fs_freq field of fstab entry */ - } - int passNumber() const { - return m_passNumber; /**< @return the fs_passno field of fstab entry */ - } - const QString& comment() const { - return m_comment; /**< @return commented part of the line in fstab file */ - } - FstabEntryType entryType() const { - return m_entryType; /**< @return the type of fstab entry, e.g. device node or UUID or comment only */ - } + /** + * @return the fs_spec field of fstab entry + */ + const QString& fsSpec() const; + /** + * @return the device node corresponding to fs_spec entry + */ + const QString& deviceNode() const; + + /** + * @return the mount point (target) for the file system + */ + const QString& mountPoint() const; + + /** + * @return the type of the file system + */ + const QString& type() const; + + /** + * @return the mount options associated with the file system + */ + const QStringList& options() const; + + /** + * @return the fs_freq field of fstab entry + */ + int dumpFreq() const; + + /** + * @return the fs_passno field of fstab entry + */ + int passNumber() const; + + /** + * @return commented part of the line in fstab file + */ + const QString& comment() const; + + /** + * @return the type of fstab entry, e.g. device node or UUID or comment only + */ + FstabEntryType entryType() const; + + /** + * @param s the new value for the fs_spec field of fstab entry + */ void setFsSpec(const QString& s); - void setMountPoint(const QString& s) { - m_mountPoint = s; /**< @param s the new value for the mount point */ - } - void setOptions(const QStringList& s) { - m_options = s; /**< @param s the new list with the mount options */ - } - void setDumpFreq(int s) { - m_dumpFreq = s; /**< @param s the new value for the dump frequency */ - } - void setPassNumber(int s) { - m_passNumber = s; /**< @param s the new value for the pass number */ - } + + /** + * @param s the new value for the mount point + */ + void setMountPoint(const QString& s); + + /** + * @param s the new list with the mount options + */ + void setOptions(const QStringList& s); + + /** + * @param s the new value for the dump frequency + */ + void setDumpFreq(int s); + + /** + * @param s the new value for the pass number + */ + void setPassNumber(int s); + private: - QString m_fsSpec; - QString m_deviceNode; - QString m_mountPoint; - QString m_type; - QStringList m_options; - int m_dumpFreq; - int m_passNumber; - QString m_comment; - FstabEntryType m_entryType; + std::shared_ptr d; }; typedef QList FstabEntryList; LIBKPMCORE_EXPORT FstabEntryList readFstabEntries(const QString& fstabPath = QStringLiteral("/etc/fstab")); LIBKPMCORE_EXPORT QStringList possibleMountPoints(const QString& deviceNode, const QString& fstabPath = QStringLiteral("/etc/fstab")); -LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList fstabEntries, const QString& filename = QStringLiteral("/etc/fstab")); +LIBKPMCORE_EXPORT bool writeMountpoints(const FstabEntryList& fstabEntries, const QString& filename = QStringLiteral("/etc/fstab")); #endif From 0b6d91bbdb3d4935f27cc175e77d415527637793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 2 Apr 2018 13:13:16 +0100 Subject: [PATCH 071/175] Do not install some private smart include files. --- src/core/CMakeLists.txt | 3 --- src/core/copysource.h | 2 -- src/core/smartattribute.h | 6 ++---- src/core/smartattributeparseddata.h | 2 +- src/core/smartdiskinformation.h | 2 +- src/core/smartparser.h | 2 +- src/core/smartstatus.h | 3 +-- src/core/volumemanagerdevice.h | 4 ++-- 8 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 584c8b4..77cc332 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -41,9 +41,6 @@ set(CORE_LIB_HDRS core/partitiontable.h core/smartattribute.h core/smartstatus.h - core/smartparser.h - core/smartattributeparseddata.h - core/smartdiskinformation.h core/volumemanagerdevice.h ) diff --git a/src/core/copysource.h b/src/core/copysource.h index f8f36b2..4e4f447 100644 --- a/src/core/copysource.h +++ b/src/core/copysource.h @@ -48,8 +48,6 @@ public: virtual qint64 firstByte() const = 0; virtual qint64 lastByte() const = 0; - -private: }; #endif diff --git a/src/core/smartattribute.h b/src/core/smartattribute.h index d0d2e2a..08687d1 100644 --- a/src/core/smartattribute.h +++ b/src/core/smartattribute.h @@ -15,15 +15,14 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_SMARTATTRIBUTE_H) - +#ifndef KPMCORE_SMARTATTRIBUTE_H #define KPMCORE_SMARTATTRIBUTE_H #include "util/libpartitionmanagerexport.h" -#include "core/smartattributeparseddata.h" #include +class SmartAttributeParsedData; class LIBKPMCORE_EXPORT SmartAttribute { @@ -104,4 +103,3 @@ private: }; #endif - diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index ef3ed51..3f1a7fc 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -15,7 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_SMARTATTRIBUTEPARSEDDATA_H) +#ifndef KPMCORE_SMARTATTRIBUTEPARSEDDATA_H #define KPMCORE_SMARTATTRIBUTEPARSEDDATA_H #include diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index 572168b..996c2fc 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -15,7 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_SMARTDISKINFORMATION_H) +#ifndef KPMCORE_SMARTDISKINFORMATION_H #define KPMCORE_SMARTDISKINFORMATION_H #include diff --git a/src/core/smartparser.h b/src/core/smartparser.h index 3438e8d..a48750c 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -15,7 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_SMARTPARSER_H) +#ifndef KPMCORE_SMARTPARSER_H #define KPMCORE_SMARTPARSER_H #include diff --git a/src/core/smartstatus.h b/src/core/smartstatus.h index 2983582..d064b7e 100644 --- a/src/core/smartstatus.h +++ b/src/core/smartstatus.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_SMARTSTATUS_H) - +#ifndef KPMCORE_SMARTSTATUS_H #define KPMCORE_SMARTSTATUS_H #include "util/libpartitionmanagerexport.h" diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index db4272e..42c84c8 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -80,9 +80,9 @@ protected: public: - /** string deviceNodes together into comma-sperated list + /** join deviceNodes together into comma-separated list * - * @return comma-seperated list of deviceNodes + * @return comma-separated list of deviceNodes */ virtual QString prettyDeviceNodeList() const; From cfa853a9312f131564a83642553237c00eb7f00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 2 Apr 2018 13:46:53 +0100 Subject: [PATCH 072/175] d-pointerize DiskDevice class. --- src/core/CMakeLists.txt | 1 - src/core/diskdevice.cpp | 59 ++++++++++++++++++++++++++++++----- src/core/diskdevice.h | 69 ++++++++++++++++++++++++----------------- 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 77cc332..504890a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -43,4 +43,3 @@ set(CORE_LIB_HDRS core/smartstatus.h core/volumemanagerdevice.h ) - diff --git a/src/core/diskdevice.cpp b/src/core/diskdevice.cpp index 6e6fac4..8922ea1 100644 --- a/src/core/diskdevice.cpp +++ b/src/core/diskdevice.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -39,14 +39,21 @@ #define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */ #endif +struct DiskDevicePrivate { + qint32 m_Heads; + qint32 m_SectorsPerTrack; + qint32 m_Cylinders; + qint64 m_LogicalSectorSize; + qint64 m_PhysicalSectorSize; +}; + static qint64 getPhysicalSectorSize(const QString& device_node) { /* * possible ways of getting the physical sector size for a drive: * - ioctl(BLKPBSZGET) -- supported with Linux 2.6.32 and later * - /sys/block/sda/queue/physical_block_size - * - libblkid from util-linux-ng 2.17 or later - * TODO: implement the blkid method + * - libblkid from util-linux 2.17 or later (not implemented) */ #if defined(BLKPBSZGET) @@ -88,10 +95,46 @@ DiskDevice::DiskDevice(const QString& name, qint64 sectorSize, const QString& iconName) : Device(name, deviceNode, sectorSize, (static_cast(heads) * cylinders * numSectors), iconName, Device::Disk_Device) - , m_Heads(heads) - , m_SectorsPerTrack(numSectors) - , m_Cylinders(cylinders) - , m_LogicalSectorSize(sectorSize) - , m_PhysicalSectorSize(getPhysicalSectorSize(deviceNode)) + , d(std::make_unique()) { + d->m_Heads = heads; + d->m_SectorsPerTrack = numSectors; + d->m_Cylinders = cylinders; + d->m_LogicalSectorSize = sectorSize; + d->m_PhysicalSectorSize = getPhysicalSectorSize(deviceNode); +} + +qint32 DiskDevice::heads() const +{ + return d->m_Heads; +} + +qint32 DiskDevice::cylinders() const +{ + return d->m_Cylinders; +} + +qint32 DiskDevice::sectorsPerTrack() const +{ + return d->m_SectorsPerTrack; +} + +qint64 DiskDevice::physicalSectorSize() const +{ + return d->m_PhysicalSectorSize; +} + +qint64 DiskDevice::logicalSectorSize() const +{ + return d->m_LogicalSectorSize; +} + +qint64 DiskDevice::totalSectors() const +{ + return static_cast(heads()) * cylinders() * sectorsPerTrack(); +} + +qint64 DiskDevice::cylinderSize() const +{ + return static_cast(heads()) * sectorsPerTrack(); } diff --git a/src/core/diskdevice.h b/src/core/diskdevice.h index 9c4a359..f535179 100644 --- a/src/core/diskdevice.h +++ b/src/core/diskdevice.h @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -15,13 +16,14 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_DISKDEVICE_H) - +#ifndef KPMCORE_DISKDEVICE_H #define KPMCORE_DISKDEVICE_H #include "util/libpartitionmanagerexport.h" #include "core/device.h" +#include + #include #include #include @@ -30,6 +32,7 @@ class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; +struct DiskDevicePrivate; /** A disk device. @@ -40,6 +43,7 @@ class SmartStatus; @see PartitionTable, Partition @author Volker Lanz */ + class LIBKPMCORE_EXPORT DiskDevice : public Device { Q_DISABLE_COPY(DiskDevice) @@ -51,34 +55,43 @@ public: DiskDevice(const QString& name, const QString& deviceNode, qint32 heads, qint32 numSectors, qint32 cylinders, qint64 sectorSize, const QString& iconName = QString()); public: - qint32 heads() const { - return m_Heads; /**< @return the number of heads on the Device in CHS notation */ - } - qint32 cylinders() const { - return m_Cylinders; /**< @return the number of cylinders on the Device in CHS notation */ - } - qint32 sectorsPerTrack() const { - return m_SectorsPerTrack; /**< @return the number of sectors on the Device in CHS notation */ - } - qint64 physicalSectorSize() const { - return m_PhysicalSectorSize; /**< @return the physical sector size the Device uses or -1 if unknown */ - } - qint64 logicalSectorSize() const { - return m_LogicalSectorSize; /**< @return the logical sector size the Device uses */ - } - qint64 totalSectors() const { - return static_cast(heads()) * cylinders() * sectorsPerTrack(); /**< @return the total number of sectors on the device */ - } - qint64 cylinderSize() const { - return static_cast(heads()) * sectorsPerTrack(); /**< @return the size of a cylinder on this Device in sectors */ - } + /** + * @return the number of heads on the Device in CHS notation + */ + qint32 heads() const; + + /** + * @return the number of cylinders on the Device in CHS notation + */ + qint32 cylinders() const; + + /** + * @return the number of sectors on the Device in CHS notation + */ + qint32 sectorsPerTrack() const; + + /** + * @return the physical sector size the Device uses or -1 if unknown + */ + qint64 physicalSectorSize() const; + + /** + * @return the logical sector size the Device uses + */ + qint64 logicalSectorSize() const; + + /** + * @return the total number of sectors on the device + */ + qint64 totalSectors() const; + + /** + * @return the size of a cylinder on this Device in sectors + */ + qint64 cylinderSize() const; private: - qint32 m_Heads; - qint32 m_SectorsPerTrack; - qint32 m_Cylinders; - qint64 m_LogicalSectorSize; - qint64 m_PhysicalSectorSize; + std::unique_ptr d; }; #endif From 54be18e8ad83e8dbbf21a9c487251bb4eac3b523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 2 Apr 2018 14:12:30 +0100 Subject: [PATCH 073/175] Deprecate cyllinder and head count. --- src/core/diskdevice.cpp | 4 ++-- src/core/diskdevice.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/diskdevice.cpp b/src/core/diskdevice.cpp index 8922ea1..6a1cdee 100644 --- a/src/core/diskdevice.cpp +++ b/src/core/diskdevice.cpp @@ -131,10 +131,10 @@ qint64 DiskDevice::logicalSectorSize() const qint64 DiskDevice::totalSectors() const { - return static_cast(heads()) * cylinders() * sectorsPerTrack(); + return static_cast(d->m_Heads) * d->m_Cylinders * d->m_SectorsPerTrack; } qint64 DiskDevice::cylinderSize() const { - return static_cast(heads()) * sectorsPerTrack(); + return static_cast(d->m_Heads) * d->m_SectorsPerTrack; } diff --git a/src/core/diskdevice.h b/src/core/diskdevice.h index f535179..5b5013c 100644 --- a/src/core/diskdevice.h +++ b/src/core/diskdevice.h @@ -58,11 +58,13 @@ public: /** * @return the number of heads on the Device in CHS notation */ + [[deprecated]] qint32 heads() const; /** * @return the number of cylinders on the Device in CHS notation */ + [[deprecated]] qint32 cylinders() const; /** From 63cea60ff12072f671ea7293c2400ea1d69397a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 5 Apr 2018 21:52:17 +0100 Subject: [PATCH 074/175] Replace std::array with std::vector Less efficient but helps with keeping ABI stable --- src/core/device.h | 3 +-- src/fs/btrfs.cpp | 2 +- src/fs/filesystem.cpp | 2 +- src/fs/filesystem.h | 6 +++--- src/gui/partwidget.cpp | 2 +- src/gui/partwidget.h | 6 ++---- 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/core/device.h b/src/core/device.h index a32f77b..db7c391 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_DEVICE_H) - +#ifndef KPMCORE_DEVICE_H #define KPMCORE_DEVICE_H #include "util/libpartitionmanagerexport.h" diff --git a/src/fs/btrfs.cpp b/src/fs/btrfs.cpp index e202213..864cf56 100644 --- a/src/fs/btrfs.cpp +++ b/src/fs/btrfs.cpp @@ -44,7 +44,7 @@ FileSystem::CommandSupportType btrfs::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType btrfs::m_GetUUID = FileSystem::cmdSupportNone; btrfs::btrfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Btrfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Btrfs) { } diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index f540145..0dea891 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -36,7 +36,7 @@ #include #include -const std::array< QColor, FileSystem::__lastType > FileSystem::defaultColorCode = +const std::vector FileSystem::defaultColorCode = { { QColor( 220,205,175 ), // unknown diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 244c83c..fb5816f 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -28,7 +28,7 @@ #include #include -#include +#include class QColor; class QValidator; @@ -57,7 +57,7 @@ public: }; /** Supported FileSystem types */ - enum Type { + enum Type : int { Unknown = 0, Extended = 1, @@ -101,7 +101,7 @@ public: cmdSupportBackend = 4 /**< supported by the backend */ }; - static const std::array< QColor, __lastType > defaultColorCode; + static const std::vector defaultColorCode; Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType) diff --git a/src/gui/partwidget.cpp b/src/gui/partwidget.cpp index 49b252f..3615c3d 100644 --- a/src/gui/partwidget.cpp +++ b/src/gui/partwidget.cpp @@ -71,7 +71,7 @@ void PartWidget::updateChildren() } } -void PartWidget::setFileSystemColorCode(const std::array< QColor, FileSystem::__lastType >& colorCode) +void PartWidget::setFileSystemColorCode(const std::vector& colorCode) { m_fileSystemColorCode = colorCode; repaint(); diff --git a/src/gui/partwidget.h b/src/gui/partwidget.h index 452aa69..8275483 100644 --- a/src/gui/partwidget.h +++ b/src/gui/partwidget.h @@ -26,8 +26,6 @@ #include -#include - class Partition; class QPaintEvent; @@ -63,7 +61,7 @@ public: return m_Partition; /**< @return the widget's Partition */ } - void setFileSystemColorCode( const std::array< QColor, FileSystem::__lastType >& colorCode ); + void setFileSystemColorCode( const std::vector& colorCode ); protected: void paintEvent(QPaintEvent* event); @@ -76,7 +74,7 @@ protected: private: Partition* m_Partition; bool m_Active; - std::array< QColor, FileSystem::__lastType > m_fileSystemColorCode; + std::vector m_fileSystemColorCode; }; #endif From 876c037ebf37871b56b9c2de53219661069f9f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 5 Apr 2018 23:06:52 +0100 Subject: [PATCH 075/175] Use strongly typed enum for SmartAttributeUnit. --- src/core/smartattribute.cpp | 14 +- src/core/smartattributeparseddata.cpp | 307 +++++++++++++------------- src/core/smartattributeparseddata.h | 83 ++++--- src/core/smartdiskinformation.cpp | 12 +- 4 files changed, 205 insertions(+), 211 deletions(-) diff --git a/src/core/smartattribute.cpp b/src/core/smartattribute.cpp index 50593d1..6e29056 100644 --- a/src/core/smartattribute.cpp +++ b/src/core/smartattribute.cpp @@ -27,7 +27,7 @@ static QString getAttrName(qint32 id); static QString getAttrDescription(qint32 id); -static QString getPrettyValue(quint64 value, qint64 unit); +static QString getPrettyValue(quint64 value, SmartAttributeUnit unit); static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a); static QString getRaw(quint64 raw); @@ -68,28 +68,28 @@ QString SmartAttribute::assessmentToString(Assessment a) } } -static QString getPrettyValue(quint64 value, qint64 unit) +static QString getPrettyValue(quint64 value, SmartAttributeUnit unit) { QString rval; switch (unit) { - case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS: + case SmartAttributeUnit::Miliseconds: rval = KFormat().formatDuration(value); break; - case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS: + case SmartAttributeUnit::Sectors: rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value); break; - case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN: + case SmartAttributeUnit::Milikelvin: rval = SmartStatus::tempToString(value); break; - case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE: + case SmartAttributeUnit::None: rval = QLocale().toString(value); break; - case SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN: + case SmartAttributeUnit::Unknown: default: rval = xi18nc("@item:intable not applicable", "N/A"); break; diff --git a/src/core/smartattributeparseddata.cpp b/src/core/smartattributeparseddata.cpp index b14e520..b310a7b 100644 --- a/src/core/smartattributeparseddata.cpp +++ b/src/core/smartattributeparseddata.cpp @@ -31,8 +31,8 @@ #define MSECOND_VALID_SHORT_MAX (60ULL * 60ULL * 1000ULL) #define MSECOND_VALID_LONG_MAX (30ULL * 365ULL * 24ULL * 60ULL * 60ULL * 1000ULL) -static const QMap tableUnit(); -static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware); +static QMap tableUnit(); +static SmartQuirk getQuirk(QString model, QString firmware); /** Creates a new SmartAttributeParsedData object. @param disk the reference to the disk that this attribute is allocated to @@ -56,9 +56,9 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, m_GoodInThePast(true), m_GoodInThePastValid(false), m_Warn(false), - m_PrettyUnit(SMART_ATTRIBUTE_UNIT_UNKNOWN), + m_PrettyUnit(SmartAttributeUnit::Unknown), m_Disk(disk), - m_Quirk((SmartAttributeParsedData::SmartQuirk) 0) + m_Quirk(SmartQuirk::None) { if (disk) m_Quirk = getQuirk(disk->model(), disk->firmware()); @@ -88,7 +88,7 @@ SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk, m_Online = flagsObj[online].toBool(); if (!updateUnit()) - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + m_PrettyUnit = SmartAttributeUnit::Unknown; makePretty(); @@ -148,7 +148,7 @@ void SmartAttributeParsedData::validateValues() /** Make a pretty value from raw based on attribute's id */ void SmartAttributeParsedData::makePretty() { - if (m_PrettyUnit == SMART_ATTRIBUTE_UNIT_UNKNOWN) + if (m_PrettyUnit == SmartAttributeUnit::Unknown) return; switch (id()) { @@ -230,41 +230,41 @@ void SmartAttributeParsedData::verifyAttribute() void SmartAttributeParsedData::verifyTemperature() { - if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MKELVIN) + if (prettyUnit() != SmartAttributeUnit::Milikelvin) return; if (prettyValue() < MKELVIN_VALID_MIN || prettyValue() > MKELVIN_VALID_MAX) - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + m_PrettyUnit = SmartAttributeUnit::Unknown; } void SmartAttributeParsedData::verifyShortTime() { - if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MSECONDS) + if (prettyUnit() != SmartAttributeUnit::Miliseconds) return; if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_SHORT_MAX) - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + m_PrettyUnit = SmartAttributeUnit::Unknown; } void SmartAttributeParsedData::verifyLongTime() { - if (prettyUnit() != SMART_ATTRIBUTE_UNIT_MSECONDS) + if (prettyUnit() != SmartAttributeUnit::Miliseconds) return; if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_LONG_MAX) - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + m_PrettyUnit = SmartAttributeUnit::Unknown; } void SmartAttributeParsedData::verifySectors() { - if (prettyUnit() != SMART_ATTRIBUTE_UNIT_SECTORS) + if (prettyUnit() != SmartAttributeUnit::Sectors) return; quint64 maxSectors = disk()->size() / 512ULL; if (prettyValue() == 0xFFFFFFFFULL || prettyValue() == 0xFFFFFFFFFFFFULL || (maxSectors > 0 && prettyValue() > maxSectors)) - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + m_PrettyUnit = SmartAttributeUnit::Unknown; else if ((id() == 5 || id() == 197) && prettyValue() > 0) m_Warn = true; } @@ -274,120 +274,120 @@ bool SmartAttributeParsedData::updateUnit() if (m_Quirk) { switch (id()) { case 3: - if (m_Quirk & SMART_QUIRK_3_UNUSED) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + if (m_Quirk & SmartQuirk::SMART_QUIRK_3_UNUSED) { + m_PrettyUnit = SmartAttributeUnit::Unknown; return true; } break; case 4: - if (m_Quirk & SMART_QUIRK_4_UNUSED) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_UNKNOWN; + if (m_Quirk & SmartQuirk::SMART_QUIRK_4_UNUSED) { + m_PrettyUnit = SmartAttributeUnit::Unknown; return true; } break; case 5: - if (m_Quirk & SMART_QUIRK_5_UNKNOWN) + if (m_Quirk & SmartQuirk::SMART_QUIRK_5_UNKNOWN) return false; break; case 9: - if (m_Quirk & SMART_QUIRK_9_POWERONMINUTES) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONMINUTES) { + m_PrettyUnit = SmartAttributeUnit::Miliseconds; return true; - } else if (m_Quirk & SMART_QUIRK_9_POWERONSECONDS) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONSECONDS) { + m_PrettyUnit = SmartAttributeUnit::Miliseconds; return true; - } else if (m_Quirk & SMART_QUIRK_9_POWERONHALFMINUTES) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES) { + m_PrettyUnit = SmartAttributeUnit::Miliseconds; return true; - } else if (m_Quirk & SMART_QUIRK_9_UNKNOWN) + } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_UNKNOWN) return false; break; case 190: - if (m_Quirk & SMART_QUIRK_190_UNKNOWN) + if (m_Quirk & SmartQuirk::SMART_QUIRK_190_UNKNOWN) return false; break; case 192: - if (m_Quirk & SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + if (m_Quirk & SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) { + m_PrettyUnit = SmartAttributeUnit::None; return true; } break; case 194: - if (m_Quirk & SMART_QUIRK_194_10XCELSIUS) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MKELVIN; + if (m_Quirk & SmartQuirk::SMART_QUIRK_194_10XCELSIUS) { + m_PrettyUnit = SmartAttributeUnit::Milikelvin; return true; - } else if (m_Quirk & SMART_QUIRK_194_UNKNOWN) + } else if (m_Quirk & SmartQuirk::SMART_QUIRK_194_UNKNOWN) return false; break; case 197: - if (m_Quirk & SMART_QUIRK_197_UNKNOWN) + if (m_Quirk & SmartQuirk::SMART_QUIRK_197_UNKNOWN) return false; break; case 198: - if (m_Quirk & SMART_QUIRK_198_UNKNOWN) + if (m_Quirk & SmartQuirk::SMART_QUIRK_198_UNKNOWN) return false; break; case 200: - if (m_Quirk & SMART_QUIRK_200_WRITEERRORCOUNT) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + if (m_Quirk & SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT) { + m_PrettyUnit = SmartAttributeUnit::None; return true; } break; case 201: - if (m_Quirk & SMART_QUIRK_201_DETECTEDTACOUNT) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_NONE; + if (m_Quirk & SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT) { + m_PrettyUnit = SmartAttributeUnit::None; return true; } break; case 225: - if (m_Quirk & SMART_QUIRK_225_TOTALLBASWRITTEN) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MB; + if (m_Quirk & SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN) { + m_PrettyUnit = SmartAttributeUnit::MB; return true; } break; case 226: - if (m_Quirk & SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; + if (m_Quirk & SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) { + m_PrettyUnit = SmartAttributeUnit::SmallPercent; return true; } break; case 227: - if (m_Quirk & SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_SMALL_PERCENT; + if (m_Quirk & SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) { + m_PrettyUnit = SmartAttributeUnit::SmallPercent; return true; } break; case 228: - if (m_Quirk & SMART_QUIRK_228_WORKLOADTIMER) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_MSECONDS; + if (m_Quirk & SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER) { + m_PrettyUnit = SmartAttributeUnit::Miliseconds; return true; } break; case 232: - if (m_Quirk & SMART_QUIRK_232_AVAILABLERESERVEDSPACE) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; + if (m_Quirk & SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE) { + m_PrettyUnit = SmartAttributeUnit::Percent; return true; } break; case 233: - if (m_Quirk & SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) { - m_PrettyUnit = SMART_ATTRIBUTE_UNIT_PERCENT; + if (m_Quirk & SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) { + m_PrettyUnit = SmartAttributeUnit::Percent; return true; } break; @@ -403,77 +403,77 @@ bool SmartAttributeParsedData::updateUnit() return false; } -static const QMap tableUnit() +static QMap tableUnit() { - QMap table; - table.insert(1, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(2, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(3, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); - table.insert(4, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(5, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); - table.insert(6, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(7, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(8, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(9, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); - table.insert(10, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(11, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(12, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(13, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(170, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_PERCENT); - table.insert(171, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(172, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(175, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(176, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(177, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(178, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(179, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(180, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(181, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(182, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(183, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(184, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(187, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); - table.insert(188, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(189, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(190, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); - table.insert(191, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(192, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(193, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(194, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); - table.insert(195, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(196, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(197, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); - table.insert(198, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); - table.insert(199, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(200, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(201, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(202, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(203, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(204, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(205, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(206, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(207, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(208, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(209, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(220, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(221, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(222, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); - table.insert(223, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(224, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(225, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(226, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); - table.insert(227, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(228, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); - table.insert(230, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(231, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN); - table.insert(232, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_PERCENT); - table.insert(233, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(234, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_SECTORS); - table.insert(235, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_UNKNOWN); - table.insert(240, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS); - table.insert(241, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MB); - table.insert(242, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MB); - table.insert(250, SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE); + QMap table; + table.insert(1, SmartAttributeUnit::None); + table.insert(2, SmartAttributeUnit::Unknown); + table.insert(3, SmartAttributeUnit::Miliseconds); + table.insert(4, SmartAttributeUnit::None); + table.insert(5, SmartAttributeUnit::Sectors); + table.insert(6, SmartAttributeUnit::Unknown); + table.insert(7, SmartAttributeUnit::None); + table.insert(8, SmartAttributeUnit::Unknown); + table.insert(9, SmartAttributeUnit::Miliseconds); + table.insert(10, SmartAttributeUnit::None); + table.insert(11, SmartAttributeUnit::None); + table.insert(12, SmartAttributeUnit::None); + table.insert(13, SmartAttributeUnit::None); + table.insert(170, SmartAttributeUnit::Percent); + table.insert(171, SmartAttributeUnit::None); + table.insert(172, SmartAttributeUnit::None); + table.insert(175, SmartAttributeUnit::None); + table.insert(176, SmartAttributeUnit::None); + table.insert(177, SmartAttributeUnit::None); + table.insert(178, SmartAttributeUnit::None); + table.insert(179, SmartAttributeUnit::None); + table.insert(180, SmartAttributeUnit::None); + table.insert(181, SmartAttributeUnit::None); + table.insert(182, SmartAttributeUnit::None); + table.insert(183, SmartAttributeUnit::None); + table.insert(184, SmartAttributeUnit::None); + table.insert(187, SmartAttributeUnit::Sectors); + table.insert(188, SmartAttributeUnit::None); + table.insert(189, SmartAttributeUnit::None); + table.insert(190, SmartAttributeUnit::Milikelvin); + table.insert(191, SmartAttributeUnit::None); + table.insert(192, SmartAttributeUnit::None); + table.insert(193, SmartAttributeUnit::None); + table.insert(194, SmartAttributeUnit::Milikelvin); + table.insert(195, SmartAttributeUnit::None); + table.insert(196, SmartAttributeUnit::None); + table.insert(197, SmartAttributeUnit::Sectors); + table.insert(198, SmartAttributeUnit::Sectors); + table.insert(199, SmartAttributeUnit::None); + table.insert(200, SmartAttributeUnit::None); + table.insert(201, SmartAttributeUnit::None); + table.insert(202, SmartAttributeUnit::None); + table.insert(203, SmartAttributeUnit::Unknown); + table.insert(204, SmartAttributeUnit::None); + table.insert(205, SmartAttributeUnit::None); + table.insert(206, SmartAttributeUnit::Unknown); + table.insert(207, SmartAttributeUnit::Unknown); + table.insert(208, SmartAttributeUnit::Unknown); + table.insert(209, SmartAttributeUnit::Unknown); + table.insert(220, SmartAttributeUnit::Unknown); + table.insert(221, SmartAttributeUnit::None); + table.insert(222, SmartAttributeUnit::Miliseconds); + table.insert(223, SmartAttributeUnit::None); + table.insert(224, SmartAttributeUnit::Unknown); + table.insert(225, SmartAttributeUnit::None); + table.insert(226, SmartAttributeUnit::Miliseconds); + table.insert(227, SmartAttributeUnit::None); + table.insert(228, SmartAttributeUnit::None); + table.insert(230, SmartAttributeUnit::Unknown); + table.insert(231, SmartAttributeUnit::Milikelvin); + table.insert(232, SmartAttributeUnit::Percent); + table.insert(233, SmartAttributeUnit::Unknown); + table.insert(234, SmartAttributeUnit::Sectors); + table.insert(235, SmartAttributeUnit::Unknown); + table.insert(240, SmartAttributeUnit::Miliseconds); + table.insert(241, SmartAttributeUnit::MB); + table.insert(242, SmartAttributeUnit::MB); + table.insert(250, SmartAttributeUnit::None); return table; } @@ -485,20 +485,20 @@ static const QVector quirkDatabase QVector quirkDb; quirkDb << QuirkDatabase(QStringLiteral("^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$"), QStringLiteral("^0085000B$"), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_197_UNKNOWN | - SmartAttributeParsedData::SMART_QUIRK_198_UNKNOWN)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | + SmartQuirk::SMART_QUIRK_197_UNKNOWN | + SmartQuirk::SMART_QUIRK_198_UNKNOWN)); quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHR2040AT$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | - SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | - SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS | + SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT)); quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHS20[6432]0AT( .)?$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS | - SmartAttributeParsedData::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | - SmartAttributeParsedData::SMART_QUIRK_200_WRITEERRORCOUNT | - SmartAttributeParsedData::SMART_QUIRK_201_DETECTEDTACOUNT)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS | + SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT | + SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT | + SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT)); quirkDb << QuirkDatabase(QStringLiteral("^(" "FUJITSU M1623TAU|" @@ -516,34 +516,33 @@ static const QVector quirkDatabase "FUJITSU MP[A-G]3...A[HTEV]U?.*" ")$"), QStringLiteral(), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONSECONDS); + SmartQuirk::SMART_QUIRK_9_POWERONSECONDS); quirkDb << QuirkDatabase(QStringLiteral("^(" "SAMSUNG SV4012H|" "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]" ")$"), QStringLiteral(), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES); quirkDb << QuirkDatabase(QStringLiteral("^(" "SAMSUNG SV0412H|" "SAMSUNG SV1204H" ")$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES | - SmartAttributeParsedData::SMART_QUIRK_194_10XCELSIUS)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES | SmartQuirk::SMART_QUIRK_194_10XCELSIUS)); quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP40A2H$"), QStringLiteral("^RR100-07$"), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES); quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP80A4H$"), QStringLiteral("^RT100-06$"), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES); quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP8004H$"), QStringLiteral("^QW100-61$"), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONHALFMINUTES); + SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES); quirkDb << QuirkDatabase(QStringLiteral("^(" "Maxtor 2B0(0[468]|1[05]|20)H1|" @@ -551,8 +550,7 @@ static const QVector quirkDatabase "Maxtor 4D0(20H1|40H2|60H3|80H4)" ")$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_194_UNKNOWN)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_194_UNKNOWN)); quirkDb << QuirkDatabase(QStringLiteral("^(" "Maxtor 2F0[234]0[JL]0|" @@ -585,7 +583,7 @@ static const QVector quirkDatabase "Maxtor 7L(25|30)0[SR]0" ")$"), QStringLiteral(), - SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES); + SmartQuirk::SMART_QUIRK_9_POWERONMINUTES); quirkDb << QuirkDatabase(QStringLiteral("^(" "HITACHI_DK14FA-20B|" @@ -595,34 +593,31 @@ static const QVector quirkDatabase "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00" ")$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_9_POWERONMINUTES | - SmartAttributeParsedData::SMART_QUIRK_193_LOADUNLOAD)); + static_cast(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_193_LOADUNLOAD)); quirkDb << QuirkDatabase(QStringLiteral("^HTS541010G9SA00$"), QStringLiteral("^MBZOC60P$"), - SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN); + SmartQuirk::SMART_QUIRK_5_UNKNOWN); quirkDb << QuirkDatabase(QStringLiteral("^MCCOE64GEMPP$"), QStringLiteral("^2.9.0[3-9]$"), - (SmartAttributeParsedData::SmartQuirk) (SmartAttributeParsedData::SMART_QUIRK_5_UNKNOWN | - SmartAttributeParsedData::SMART_QUIRK_190_UNKNOWN)); + static_cast(SmartQuirk::SMART_QUIRK_5_UNKNOWN | SmartQuirk::SMART_QUIRK_190_UNKNOWN)); quirkDb << QuirkDatabase(QStringLiteral("^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$"), QStringLiteral(), - (SmartAttributeParsedData::SmartQuirk) - (SmartAttributeParsedData::SMART_QUIRK_3_UNUSED | - SmartAttributeParsedData::SMART_QUIRK_4_UNUSED | - SmartAttributeParsedData::SMART_QUIRK_225_TOTALLBASWRITTEN | - SmartAttributeParsedData::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR | - SmartAttributeParsedData::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS | - SmartAttributeParsedData::SMART_QUIRK_228_WORKLOADTIMER | - SmartAttributeParsedData::SMART_QUIRK_232_AVAILABLERESERVEDSPACE | - SmartAttributeParsedData::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR)); + static_cast(SmartQuirk::SMART_QUIRK_3_UNUSED | + SmartQuirk::SMART_QUIRK_4_UNUSED | + SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN | + SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR | + SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS | + SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER | + SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE | + SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR)); return quirkDb; } -static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firmware) +static SmartQuirk getQuirk(QString model, QString firmware) { const QVector db = quirkDatabase(); @@ -645,5 +640,5 @@ static SmartAttributeParsedData::SmartQuirk getQuirk(QString model, QString firm return item.quirk; } - return (SmartAttributeParsedData::SmartQuirk) 0; + return SmartQuirk::None; } diff --git a/src/core/smartattributeparseddata.h b/src/core/smartattributeparseddata.h index 3f1a7fc..014c277 100644 --- a/src/core/smartattributeparseddata.h +++ b/src/core/smartattributeparseddata.h @@ -23,6 +23,45 @@ class SmartDiskInformation; +/** SMART Quirk */ +enum SmartQuirk { + None = 0x000000, + SMART_QUIRK_9_POWERONMINUTES = 0x000001, + SMART_QUIRK_9_POWERONSECONDS = 0x000002, + SMART_QUIRK_9_POWERONHALFMINUTES = 0x000004, + SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x000008, + SMART_QUIRK_193_LOADUNLOAD = 0x000010, + SMART_QUIRK_194_10XCELSIUS = 0x000020, + SMART_QUIRK_194_UNKNOWN = 0x000040, + SMART_QUIRK_200_WRITEERRORCOUNT = 0x000080, + SMART_QUIRK_201_DETECTEDTACOUNT = 0x000100, + SMART_QUIRK_5_UNKNOWN = 0x000200, + SMART_QUIRK_9_UNKNOWN = 0x000400, + SMART_QUIRK_197_UNKNOWN = 0x000800, + SMART_QUIRK_198_UNKNOWN = 0x001000, + SMART_QUIRK_190_UNKNOWN = 0x002000, + SMART_QUIRK_232_AVAILABLERESERVEDSPACE = 0x004000, + SMART_QUIRK_233_MEDIAWEAROUTINDICATOR = 0x008000, + SMART_QUIRK_225_TOTALLBASWRITTEN = 0x010000, + SMART_QUIRK_4_UNUSED = 0x020000, + SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR = 0x040000, + SMART_QUIRK_227_TIMEWORKLOADHOSTREADS = 0x080000, + SMART_QUIRK_228_WORKLOADTIMER = 0x100000, + SMART_QUIRK_3_UNUSED = 0x200000, +}; + +/** A unit for SMART attributes */ +enum class SmartAttributeUnit { + Unknown, + None, + Miliseconds, + Sectors, + Milikelvin, + SmallPercent, /* percentage with 3 decimal points */ + Percent, + MB, +}; + /** A SMART parsed attribute. It receives the attribute data from JSON, retrieve its data and validates its values. @@ -32,55 +71,15 @@ class SmartDiskInformation; class SmartAttributeParsedData { public: - - /** A unit for SMART attributes */ - enum SmartAttributeUnit { - SMART_ATTRIBUTE_UNIT_UNKNOWN, - SMART_ATTRIBUTE_UNIT_NONE, - SMART_ATTRIBUTE_UNIT_MSECONDS, - SMART_ATTRIBUTE_UNIT_SECTORS, - SMART_ATTRIBUTE_UNIT_MKELVIN, - SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, - SMART_ATTRIBUTE_UNIT_PERCENT, - SMART_ATTRIBUTE_UNIT_MB, - _SMART_ATTRIBUTE_UNIT_MAX - }; - - /** SMART Quirk */ - enum SmartQuirk { - SMART_QUIRK_9_POWERONMINUTES = 0x000001, - SMART_QUIRK_9_POWERONSECONDS = 0x000002, - SMART_QUIRK_9_POWERONHALFMINUTES = 0x000004, - SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x000008, - SMART_QUIRK_193_LOADUNLOAD = 0x000010, - SMART_QUIRK_194_10XCELSIUS = 0x000020, - SMART_QUIRK_194_UNKNOWN = 0x000040, - SMART_QUIRK_200_WRITEERRORCOUNT = 0x000080, - SMART_QUIRK_201_DETECTEDTACOUNT = 0x000100, - SMART_QUIRK_5_UNKNOWN = 0x000200, - SMART_QUIRK_9_UNKNOWN = 0x000400, - SMART_QUIRK_197_UNKNOWN = 0x000800, - SMART_QUIRK_198_UNKNOWN = 0x001000, - SMART_QUIRK_190_UNKNOWN = 0x002000, - SMART_QUIRK_232_AVAILABLERESERVEDSPACE = 0x004000, - SMART_QUIRK_233_MEDIAWEAROUTINDICATOR = 0x008000, - SMART_QUIRK_225_TOTALLBASWRITTEN = 0x010000, - SMART_QUIRK_4_UNUSED = 0x020000, - SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR = 0x040000, - SMART_QUIRK_227_TIMEWORKLOADHOSTREADS = 0x080000, - SMART_QUIRK_228_WORKLOADTIMER = 0x100000, - SMART_QUIRK_3_UNUSED = 0x200000 - }; - /** SMART Quirk to some particular model and firmware */ struct SmartQuirkDataBase { QString model; QString firmware; - SmartAttributeParsedData::SmartQuirk quirk; + SmartQuirk quirk; SmartQuirkDataBase(const QString &m = QString(), const QString &f = QString(), - SmartAttributeParsedData::SmartQuirk q = (SmartAttributeParsedData::SmartQuirk) 0) : + SmartQuirk q = SmartQuirk::None) : model(m), firmware(f), quirk(q) diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index f227692..fc46d21 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -108,16 +108,16 @@ bool SmartDiskInformation::updateTemperature() airflowTemperatureCelsius = findAttribute(190); if (temperatureCelsius != nullptr - && temperatureCelsius->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + && temperatureCelsius->prettyUnit() == SmartAttributeUnit::Milikelvin) { m_Temperature = temperatureCelsius->prettyValue(); return true; } else if (temperatureCelsius2 != nullptr - && temperatureCelsius2->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + && temperatureCelsius2->prettyUnit() == SmartAttributeUnit::Milikelvin) { m_Temperature = temperatureCelsius2->prettyValue(); return true; } else if (airflowTemperatureCelsius != nullptr && airflowTemperatureCelsius->prettyUnit() == - SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MKELVIN) { + SmartAttributeUnit::Milikelvin) { m_Temperature = airflowTemperatureCelsius->prettyValue(); return true; } @@ -136,11 +136,11 @@ bool SmartDiskInformation::updatePowerOn() powerOnSeconds = findAttribute(233); if (powerOnHours != nullptr - && powerOnHours->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS) { + && powerOnHours->prettyUnit() == SmartAttributeUnit::Miliseconds) { m_PoweredOn = powerOnHours->prettyValue(); return true; } else if (powerOnSeconds != nullptr - && powerOnSeconds->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_MSECONDS) { + && powerOnSeconds->prettyUnit() == SmartAttributeUnit::Miliseconds) { m_PoweredOn = powerOnSeconds->prettyValue(); return true; } @@ -157,7 +157,7 @@ bool SmartDiskInformation::updatePowerCycle() powerCycleCount = findAttribute(12); if (powerCycleCount != nullptr - && powerCycleCount->prettyUnit() == SmartAttributeParsedData::SMART_ATTRIBUTE_UNIT_NONE) { + && powerCycleCount->prettyUnit() == SmartAttributeUnit::None) { m_PowerCycles = powerCycleCount->prettyValue(); return true; } From 17c87722409ff75542321369857edea5aa6ef320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 7 Apr 2018 19:54:30 +0100 Subject: [PATCH 076/175] Explicitely specify the scope of enum. --- src/core/lvmdevice.cpp | 6 +- src/core/partitiontable.cpp | 2 +- src/fs/exfat.cpp | 2 +- src/fs/ext2.h | 2 +- src/fs/ext3.cpp | 2 +- src/fs/ext4.cpp | 2 +- src/fs/extended.cpp | 2 +- src/fs/f2fs.cpp | 2 +- src/fs/fat12.h | 2 +- src/fs/fat16.cpp | 2 +- src/fs/fat32.cpp | 2 +- src/fs/filesystem.cpp | 17 ++- src/fs/filesystem.h | 66 +++++------ src/fs/filesystemfactory.cpp | 120 ++++++++++---------- src/fs/filesystemfactory.h | 3 +- src/fs/hfs.cpp | 2 +- src/fs/hfsplus.cpp | 2 +- src/fs/hpfs.cpp | 2 +- src/fs/iso9660.cpp | 2 +- src/fs/jfs.cpp | 2 +- src/fs/linuxswap.cpp | 2 +- src/fs/luks.cpp | 30 ++--- src/fs/luks.h | 2 +- src/fs/luks2.cpp | 4 +- src/fs/lvm2_pv.cpp | 6 +- src/fs/nilfs2.cpp | 2 +- src/fs/ntfs.cpp | 2 +- src/fs/ocfs2.cpp | 2 +- src/fs/reiser4.cpp | 2 +- src/fs/reiserfs.cpp | 2 +- src/fs/udf.cpp | 2 +- src/fs/ufs.cpp | 2 +- src/fs/unformatted.cpp | 2 +- src/fs/unknown.cpp | 2 +- src/fs/xfs.cpp | 2 +- src/fs/zfs.cpp | 2 +- src/gui/partwidget.cpp | 4 +- src/jobs/createfilesystemjob.cpp | 2 +- src/jobs/restorefilesystemjob.cpp | 2 +- src/ops/newoperation.cpp | 4 +- src/ops/removevolumegroupoperation.cpp | 2 +- src/ops/restoreoperation.cpp | 2 +- src/plugins/dummy/dummybackend.cpp | 2 +- src/plugins/dummy/dummypartitiontable.cpp | 2 +- src/plugins/sfdisk/sfdiskbackend.cpp | 64 +++++------ src/plugins/sfdisk/sfdiskpartitiontable.cpp | 38 +++---- 46 files changed, 214 insertions(+), 216 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index e95b2a5..0799c54 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -129,7 +129,7 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl bool mounted; // Handle LUKS partition - if (fs->type() == FileSystem::Luks) { + if (fs->type() == FileSystem::Type::Luks) { r |= PartitionRole::Luks; FS::luks* luksFs = static_cast(fs); luksFs->initLUKS(); @@ -141,9 +141,9 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl mountPoint = FileSystem::detectMountPoint(fs, lvPath); mounted = FileSystem::detectMountStatus(fs, lvPath); - if (mountPoint != QString() && fs->type() != FileSystem::LinuxSwap) { + if (mountPoint != QString() && fs->type() != FileSystem::Type::LinuxSwap) { const QStorageInfo storage = QStorageInfo(mountPoint); - if (logicalSize() > 0 && fs->type() != FileSystem::Luks && mounted && storage.isValid()) + if (logicalSize() > 0 && fs->type() != FileSystem::Type::Luks && mounted && storage.isValid()) fs->setSectorsUsed( (storage.bytesTotal() - storage.bytesFree()) / logicalSize() ); } else if (fs->supportGetUsed() == FileSystem::cmdSupportFileSystem) diff --git a/src/core/partitiontable.cpp b/src/core/partitiontable.cpp index 98c1d06..aca5149 100644 --- a/src/core/partitiontable.cpp +++ b/src/core/partitiontable.cpp @@ -325,7 +325,7 @@ Partition* createUnallocated(const Device& device, PartitionNode& parent, qint64 if (!PartitionTable::getUnallocatedRange(device, parent, start, end)) return nullptr; - return new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Unknown, start, end, device.logicalSize()), start, end, QString()); + return new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Type::Unknown, start, end, device.logicalSize()), start, end, QString()); } /** Removes all unallocated children from a PartitionNode diff --git a/src/fs/exfat.cpp b/src/fs/exfat.cpp index 00bfe51..46753e8 100644 --- a/src/fs/exfat.cpp +++ b/src/fs/exfat.cpp @@ -39,7 +39,7 @@ FileSystem::CommandSupportType exfat::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_GetUUID = FileSystem::cmdSupportNone; exfat::exfat(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Exfat) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Exfat) { } diff --git a/src/fs/ext2.h b/src/fs/ext2.h index a31265d..ec2ca59 100644 --- a/src/fs/ext2.h +++ b/src/fs/ext2.h @@ -37,7 +37,7 @@ namespace FS class LIBKPMCORE_EXPORT ext2 : public FileSystem { public: - ext2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Ext2); + ext2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Ext2); public: void init() override; diff --git a/src/fs/ext3.cpp b/src/fs/ext3.cpp index 28d3710..a33f236 100644 --- a/src/fs/ext3.cpp +++ b/src/fs/ext3.cpp @@ -25,7 +25,7 @@ namespace FS { ext3::ext3(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - ext2(firstsector, lastsector, sectorsused, label, FileSystem::Ext3) + ext2(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ext3) { } diff --git a/src/fs/ext4.cpp b/src/fs/ext4.cpp index 4a12831..30d38dc 100644 --- a/src/fs/ext4.cpp +++ b/src/fs/ext4.cpp @@ -25,7 +25,7 @@ namespace FS { ext4::ext4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - ext2(firstsector, lastsector, sectorsused, label, FileSystem::Ext4) + ext2(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ext4) { } diff --git a/src/fs/extended.cpp b/src/fs/extended.cpp index 86e8420..49ab801 100644 --- a/src/fs/extended.cpp +++ b/src/fs/extended.cpp @@ -25,7 +25,7 @@ FileSystem::CommandSupportType extended::m_Shrink = FileSystem::cmdSupportCore; FileSystem::CommandSupportType extended::m_Move = FileSystem::cmdSupportCore; extended::extended(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Extended) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Extended) { } diff --git a/src/fs/f2fs.cpp b/src/fs/f2fs.cpp index 3bf3d73..d112dac 100644 --- a/src/fs/f2fs.cpp +++ b/src/fs/f2fs.cpp @@ -46,7 +46,7 @@ FileSystem::CommandSupportType f2fs::m_GetUUID = FileSystem::cmdSupportNone; bool f2fs::oldVersion = false; // 1.8.x or older f2fs::f2fs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::F2fs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::F2fs) { } diff --git a/src/fs/fat12.h b/src/fs/fat12.h index a05dd67..ef8818f 100644 --- a/src/fs/fat12.h +++ b/src/fs/fat12.h @@ -38,7 +38,7 @@ namespace FS class LIBKPMCORE_EXPORT fat12 : public FileSystem { public: - fat12(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Fat12); + fat12(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Fat12); public: void init() override; diff --git a/src/fs/fat16.cpp b/src/fs/fat16.cpp index a287385..1b6b3fe 100644 --- a/src/fs/fat16.cpp +++ b/src/fs/fat16.cpp @@ -33,7 +33,7 @@ namespace FS { fat16::fat16(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - fat12(firstsector, lastsector, sectorsused, label, FileSystem::Fat16) + fat12(firstsector, lastsector, sectorsused, label, FileSystem::Type::Fat16) { } diff --git a/src/fs/fat32.cpp b/src/fs/fat32.cpp index 05e30c8..7f6151e 100644 --- a/src/fs/fat32.cpp +++ b/src/fs/fat32.cpp @@ -26,7 +26,7 @@ namespace FS { fat32::fat32(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - fat16(firstsector, lastsector, sectorsused, label, FileSystem::Fat32) + fat16(firstsector, lastsector, sectorsused, label, FileSystem::Type::Fat32) { } diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 0dea891..9dc6c77 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -108,7 +108,7 @@ FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath) QString FileSystem::detectMountPoint(FileSystem* fs, const QString& partitionPath) { - if (fs->type() == FileSystem::Lvm2_PV) + if (fs->type() == FileSystem::Type::Lvm2_PV) return FS::lvm2_pv::getVGName(partitionPath); if (partitionPath.isEmpty()) // Happens when during initial scan LUKS is closed @@ -133,7 +133,7 @@ bool FileSystem::detectMountStatus(FileSystem* fs, const QString& partitionPath) { bool mounted = false; - if (fs->type() == FileSystem::Lvm2_PV) { + if (fs->type() == FileSystem::Type::Lvm2_PV) { mounted = FS::lvm2_pv::getVGName(partitionPath) != QString(); } else { mounted = isMounted(partitionPath); @@ -437,10 +437,9 @@ static const KLocalizedString* typeNames() */ QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages) { - Q_ASSERT(t >= 0); - Q_ASSERT(t < __lastType); + Q_ASSERT(t < Type::__lastType); - return typeNames()[t].toString(languages); + return typeNames()[static_cast(t)].toString(languages); } /** @param s the name to get the type for @@ -448,11 +447,11 @@ QString FileSystem::nameForType(FileSystem::Type t, const QStringList& languages */ FileSystem::Type FileSystem::typeForName(const QString& s, const QStringList& languages ) { - for (quint32 i = 0; i < __lastType; i++) + for (quint32 i = 0; i < static_cast(Type::__lastType); i++) if (typeNames()[i].toString(languages) == s) return static_cast(i); - return Unknown; + return Type::Unknown; } /** @return a QList of all known types */ @@ -460,8 +459,8 @@ QList FileSystem::types() { QList result; - int i = Ext2; // first "real" filesystem - while (i != __lastType) + int i = static_cast(Type::Ext2); // first "real" filesystem + while (i != static_cast(Type::__lastType)) result.append(static_cast(i++)); return result; diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index fb5816f..fc63463 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -1,7 +1,7 @@ /************************************************************************* * Copyright (C) 2012 by Volker Lanz * * Copyright (C) 2015 by Teo Mrnjavac * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -17,7 +17,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_FILESYSTEM_H) +#ifndef KPMCORE_FILESYSTEM_H #define KPMCORE_FILESYSTEM_H #include "util/libpartitionmanagerexport.h" @@ -58,39 +58,39 @@ public: /** Supported FileSystem types */ enum Type : int { - Unknown = 0, - Extended = 1, + Unknown, + Extended, - Ext2 = 2, - Ext3 = 3, - Ext4 = 4, - LinuxSwap = 5, - Fat16 = 6, - Fat32 = 7, - Ntfs = 8, - ReiserFS = 9, - Reiser4 = 10, - Xfs = 11, - Jfs = 12, - Hfs = 13, - HfsPlus = 14, - Ufs = 15, - Unformatted = 16, - Btrfs = 17, - Hpfs = 18, - Luks = 19, - Ocfs2 = 20, - Zfs = 21, - Exfat = 22, - Nilfs2 = 23, - Lvm2_PV = 24, - F2fs = 25, - Udf = 26, - Iso9660 = 27, - Luks2 = 28, - Fat12 = 29, + Ext2, + Ext3, + Ext4, + LinuxSwap, + Fat16, + Fat32, + Ntfs, + ReiserFS, + Reiser4, + Xfs, + Jfs, + Hfs, + HfsPlus, + Ufs, + Unformatted, + Btrfs, + Hpfs, + Luks, + Ocfs2, + Zfs, + Exfat, + Nilfs2, + Lvm2_PV, + F2fs, + Udf, + Iso9660, + Luks2, + Fat12, - __lastType = 30 + __lastType }; /** The type of support for a given FileSystem action */ diff --git a/src/fs/filesystemfactory.cpp b/src/fs/filesystemfactory.cpp index b17998f..fa6b120 100644 --- a/src/fs/filesystemfactory.cpp +++ b/src/fs/filesystemfactory.cpp @@ -61,36 +61,36 @@ void FileSystemFactory::init() qDeleteAll(m_FileSystems); m_FileSystems.clear(); - m_FileSystems.insert(FileSystem::Btrfs, new FS::btrfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Exfat, new FS::exfat(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ext2, new FS::ext2(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ext3, new FS::ext3(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ext4, new FS::ext4(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Extended, new FS::extended(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::F2fs, new FS::f2fs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Fat12, new FS::fat12(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Fat16, new FS::fat16(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Fat32, new FS::fat32(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Hfs, new FS::hfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::HfsPlus, new FS::hfsplus(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Hpfs, new FS::hpfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Iso9660, new FS::iso9660(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Jfs, new FS::jfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Luks, new FS::luks(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Luks2, new FS::luks2(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Nilfs2, new FS::nilfs2(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ntfs, new FS::ntfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ocfs2, new FS::ocfs2(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::ReiserFS, new FS::reiserfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Reiser4, new FS::reiser4(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Udf, new FS::udf(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Ufs, new FS::ufs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Unformatted, new FS::unformatted(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Unknown, new FS::unknown(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Xfs, new FS::xfs(-1, -1, -1, QString())); - m_FileSystems.insert(FileSystem::Zfs, new FS::zfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Btrfs, new FS::btrfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Exfat, new FS::exfat(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ext2, new FS::ext2(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ext3, new FS::ext3(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ext4, new FS::ext4(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Extended, new FS::extended(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::F2fs, new FS::f2fs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Fat12, new FS::fat12(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Fat16, new FS::fat16(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Fat32, new FS::fat32(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Hfs, new FS::hfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::HfsPlus, new FS::hfsplus(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Hpfs, new FS::hpfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Iso9660, new FS::iso9660(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Jfs, new FS::jfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Luks, new FS::luks(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Luks2, new FS::luks2(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Lvm2_PV, new FS::lvm2_pv(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Nilfs2, new FS::nilfs2(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ntfs, new FS::ntfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ocfs2, new FS::ocfs2(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::ReiserFS, new FS::reiserfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Reiser4, new FS::reiser4(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Udf, new FS::udf(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Ufs, new FS::ufs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Unformatted, new FS::unformatted(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Unknown, new FS::unknown(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Xfs, new FS::xfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::Zfs, new FS::zfs(-1, -1, -1, QString())); for (const auto &fs : FileSystemFactory::map()) fs->init(); @@ -111,36 +111,36 @@ FileSystem* FileSystemFactory::create(FileSystem::Type t, qint64 firstsector, qi FileSystem* fs = nullptr; switch (t) { - case FileSystem::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break; - case FileSystem::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break; default: break; } diff --git a/src/fs/filesystemfactory.h b/src/fs/filesystemfactory.h index 185bc57..6679bbc 100644 --- a/src/fs/filesystemfactory.h +++ b/src/fs/filesystemfactory.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_FILESYSTEMFACTORY_H) - +#ifndef KPMCORE_FILESYSTEMFACTORY_H #define KPMCORE_FILESYSTEMFACTORY_H #include "fs/filesystem.h" diff --git a/src/fs/hfs.cpp b/src/fs/hfs.cpp index 404a4d9..98a2d15 100644 --- a/src/fs/hfs.cpp +++ b/src/fs/hfs.cpp @@ -35,7 +35,7 @@ FileSystem::CommandSupportType hfs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_Backup = FileSystem::cmdSupportNone; hfs::hfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Hfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Hfs) { } diff --git a/src/fs/hfsplus.cpp b/src/fs/hfsplus.cpp index 328d356..f417ea0 100644 --- a/src/fs/hfsplus.cpp +++ b/src/fs/hfsplus.cpp @@ -35,7 +35,7 @@ FileSystem::CommandSupportType hfsplus::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Backup = FileSystem::cmdSupportNone; hfsplus::hfsplus(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::HfsPlus) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::HfsPlus) { } diff --git a/src/fs/hpfs.cpp b/src/fs/hpfs.cpp index cfb2386..aa1941e 100644 --- a/src/fs/hpfs.cpp +++ b/src/fs/hpfs.cpp @@ -37,7 +37,7 @@ FileSystem::CommandSupportType hpfs::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_GetUUID = FileSystem::cmdSupportNone; hpfs::hpfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Hpfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Hpfs) { } diff --git a/src/fs/iso9660.cpp b/src/fs/iso9660.cpp index 05d178b..d7939a9 100644 --- a/src/fs/iso9660.cpp +++ b/src/fs/iso9660.cpp @@ -21,7 +21,7 @@ namespace FS { iso9660::iso9660(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Iso9660) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Iso9660) { } diff --git a/src/fs/jfs.cpp b/src/fs/jfs.cpp index 90ab7ba..da260a4 100644 --- a/src/fs/jfs.cpp +++ b/src/fs/jfs.cpp @@ -40,7 +40,7 @@ FileSystem::CommandSupportType jfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_SetLabel = FileSystem::cmdSupportNone; jfs::jfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Jfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Jfs) { } diff --git a/src/fs/linuxswap.cpp b/src/fs/linuxswap.cpp index edffc94..b4eebdd 100644 --- a/src/fs/linuxswap.cpp +++ b/src/fs/linuxswap.cpp @@ -40,7 +40,7 @@ FileSystem::CommandSupportType linuxswap::m_GetUUID = FileSystem::cmdSupportNone FileSystem::CommandSupportType linuxswap::m_UpdateUUID = FileSystem::cmdSupportNone; linuxswap::linuxswap(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::LinuxSwap) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::LinuxSwap) { } diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index b82f64f..224c27d 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -288,7 +288,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) return false; for (auto &p : LVM::pvList) - if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Lvm2_PV) + if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Type::Lvm2_PV) p.setLuks(false); m_passphrase = passphrase; @@ -465,7 +465,7 @@ FileSystem::Type luks::type() const { if (m_isCryptOpen && m_innerFs) return m_innerFs->type(); - return FileSystem::Luks; + return FileSystem::Type::Luks; } QString luks::suggestedMapperName(const QString& deviceNode) const @@ -648,19 +648,19 @@ bool luks::canEncryptType(FileSystem::Type type) { switch (type) { - case Btrfs: - case F2fs: - case Ext2: - case Ext3: - case Ext4: - case Jfs: - case LinuxSwap: - case Lvm2_PV: - case Nilfs2: - case ReiserFS: - case Reiser4: - case Xfs: - case Zfs: + case Type::Btrfs: + case Type::F2fs: + case Type::Ext2: + case Type::Ext3: + case Type::Ext4: + case Type::Jfs: + case Type::LinuxSwap: + case Type::Lvm2_PV: + case Type::Nilfs2: + case Type::ReiserFS: + case Type::Reiser4: + case Type::Xfs: + case Type::Zfs: return true; default: return false; diff --git a/src/fs/luks.h b/src/fs/luks.h index bbcab61..dfc761f 100644 --- a/src/fs/luks.h +++ b/src/fs/luks.h @@ -40,7 +40,7 @@ namespace FS class LIBKPMCORE_EXPORT luks : public FileSystem { public: - luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Luks); + luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Luks); ~luks() override; enum KeyLocation { diff --git a/src/fs/luks2.cpp b/src/fs/luks2.cpp index 9453ee1..af2ae34 100644 --- a/src/fs/luks2.cpp +++ b/src/fs/luks2.cpp @@ -28,7 +28,7 @@ namespace FS { luks2::luks2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) - : luks(firstsector, lastsector, sectorsused, label, FileSystem::Luks2) + : luks(firstsector, lastsector, sectorsused, label, FileSystem::Type::Luks2) { } @@ -40,7 +40,7 @@ FileSystem::Type luks2::type() const { if (m_isCryptOpen && m_innerFs) return m_innerFs->type(); - return FileSystem::Luks2; + return FileSystem::Type::Luks2; } bool luks2::create(Report& report, const QString& deviceNode) diff --git a/src/fs/lvm2_pv.cpp b/src/fs/lvm2_pv.cpp index 91964ac..62791c8 100644 --- a/src/fs/lvm2_pv.cpp +++ b/src/fs/lvm2_pv.cpp @@ -43,7 +43,7 @@ FileSystem::CommandSupportType lvm2_pv::m_GetUUID = FileSystem::cmdSupportNone; lvm2_pv::lvm2_pv(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) - : FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Lvm2_PV) + : FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Lvm2_PV) , m_PESize(0) , m_TotalPE(0) , m_AllocatedPE(0) @@ -270,10 +270,10 @@ QList lvm2_pv::getPVinNode(const PartitionNode* parent) partitions.append(getPVinNode(node)); // FIXME: reenable newly created PVs (before applying) once everything works - if(p->fileSystem().type() == FileSystem::Lvm2_PV && p->deviceNode() == p->partitionPath()) + if(p->fileSystem().type() == FileSystem::Type::Lvm2_PV && p->deviceNode() == p->partitionPath()) partitions.append(LvmPV(p->mountPoint(), p)); - if(p->fileSystem().type() == FileSystem::Luks && p->deviceNode() == p->partitionPath()) + if(p->fileSystem().type() == FileSystem::Type::Luks && p->deviceNode() == p->partitionPath()) partitions.append(LvmPV(p->mountPoint(), p, true)); } diff --git a/src/fs/nilfs2.cpp b/src/fs/nilfs2.cpp index d8eb131..ffb3a69 100644 --- a/src/fs/nilfs2.cpp +++ b/src/fs/nilfs2.cpp @@ -47,7 +47,7 @@ FileSystem::CommandSupportType nilfs2::m_UpdateUUID = FileSystem::cmdSupportNone FileSystem::CommandSupportType nilfs2::m_GetUUID = FileSystem::cmdSupportNone; nilfs2::nilfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Nilfs2) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Nilfs2) { } diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index f068624..8164f18 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -50,7 +50,7 @@ FileSystem::CommandSupportType ntfs::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_GetUUID = FileSystem::cmdSupportNone; ntfs::ntfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ntfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ntfs) { } diff --git a/src/fs/ocfs2.cpp b/src/fs/ocfs2.cpp index 03720c4..040e5b3 100644 --- a/src/fs/ocfs2.cpp +++ b/src/fs/ocfs2.cpp @@ -40,7 +40,7 @@ FileSystem::CommandSupportType ocfs2::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_GetUUID = FileSystem::cmdSupportNone; ocfs2::ocfs2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ocfs2) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ocfs2) { } diff --git a/src/fs/reiser4.cpp b/src/fs/reiser4.cpp index 9d54b66..71d1830 100644 --- a/src/fs/reiser4.cpp +++ b/src/fs/reiser4.cpp @@ -35,7 +35,7 @@ FileSystem::CommandSupportType reiser4::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiser4::m_Backup = FileSystem::cmdSupportNone; reiser4::reiser4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Reiser4) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Reiser4) { } diff --git a/src/fs/reiserfs.cpp b/src/fs/reiserfs.cpp index 2f8a7ef..cb78ecf 100644 --- a/src/fs/reiserfs.cpp +++ b/src/fs/reiserfs.cpp @@ -42,7 +42,7 @@ FileSystem::CommandSupportType reiserfs::m_UpdateUUID = FileSystem::cmdSupportNo FileSystem::CommandSupportType reiserfs::m_GetUUID = FileSystem::cmdSupportNone; reiserfs::reiserfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::ReiserFS) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::ReiserFS) { } diff --git a/src/fs/udf.cpp b/src/fs/udf.cpp index f34c5f3..b0d28a9 100644 --- a/src/fs/udf.cpp +++ b/src/fs/udf.cpp @@ -40,7 +40,7 @@ FileSystem::CommandSupportType udf::m_Create = FileSystem::cmdSupportNone; bool udf::oldMkudffsVersion = false; udf::udf(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Udf) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Udf) { } diff --git a/src/fs/ufs.cpp b/src/fs/ufs.cpp index f1e7212..71f5e51 100644 --- a/src/fs/ufs.cpp +++ b/src/fs/ufs.cpp @@ -24,7 +24,7 @@ FileSystem::CommandSupportType ufs::m_Copy = FileSystem::cmdSupportCore; FileSystem::CommandSupportType ufs::m_Backup = FileSystem::cmdSupportCore; ufs::ufs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Ufs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Ufs) { } } diff --git a/src/fs/unformatted.cpp b/src/fs/unformatted.cpp index f3bcb29..e1813de 100644 --- a/src/fs/unformatted.cpp +++ b/src/fs/unformatted.cpp @@ -22,7 +22,7 @@ namespace FS FileSystem::CommandSupportType unformatted::m_Create = FileSystem::cmdSupportFileSystem; unformatted::unformatted(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Unformatted) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Unformatted) { } diff --git a/src/fs/unknown.cpp b/src/fs/unknown.cpp index 5b0a552..3f6e27f 100644 --- a/src/fs/unknown.cpp +++ b/src/fs/unknown.cpp @@ -20,7 +20,7 @@ namespace FS { unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Unknown) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Unknown) { } diff --git a/src/fs/xfs.cpp b/src/fs/xfs.cpp index f808a3e..e0b3339 100644 --- a/src/fs/xfs.cpp +++ b/src/fs/xfs.cpp @@ -42,7 +42,7 @@ FileSystem::CommandSupportType xfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_SetLabel = FileSystem::cmdSupportNone; xfs::xfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Xfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Xfs) { } diff --git a/src/fs/zfs.cpp b/src/fs/zfs.cpp index fccf00a..d04de16 100644 --- a/src/fs/zfs.cpp +++ b/src/fs/zfs.cpp @@ -40,7 +40,7 @@ FileSystem::CommandSupportType zfs::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_GetUUID = FileSystem::cmdSupportNone; zfs::zfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : - FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Zfs) + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::Zfs) { } diff --git a/src/gui/partwidget.cpp b/src/gui/partwidget.cpp index 3615c3d..d728c23 100644 --- a/src/gui/partwidget.cpp +++ b/src/gui/partwidget.cpp @@ -101,12 +101,12 @@ void PartWidget::paintEvent(QPaintEvent*) if (partition()->roles().has(PartitionRole::Extended)) { drawGradient(&painter, activeColor( - m_fileSystemColorCode[ partition()->fileSystem().type() ]), + m_fileSystemColorCode[ static_cast(partition()->fileSystem().type()) ]), QRect(0, 0, width(), height())); return; } - const QColor base = activeColor(m_fileSystemColorCode[ partition()->fileSystem().type() ]); + const QColor base = activeColor(m_fileSystemColorCode[ static_cast(partition()->fileSystem().type()) ]); if (!partition()->roles().has(PartitionRole::Unallocated)) { const QColor dark = base.darker(105); diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index 09e63a2..c4894e3 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -49,7 +49,7 @@ bool CreateFileSystemJob::run(Report& parent) Report* report = jobStarted(parent); - if (partition().fileSystem().type() == FileSystem::Unformatted) + if (partition().fileSystem().type() == FileSystem::Type::Unformatted) return true; bool createResult; diff --git a/src/jobs/restorefilesystemjob.cpp b/src/jobs/restorefilesystemjob.cpp index fc62906..c7ec7e4 100644 --- a/src/jobs/restorefilesystemjob.cpp +++ b/src/jobs/restorefilesystemjob.cpp @@ -82,7 +82,7 @@ bool RestoreFileSystemJob::run(Report& parent) std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(targetDevice()); - FileSystem::Type t = FileSystem::Unknown; + FileSystem::Type t = FileSystem::Type::Unknown; if (backendDevice) { std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); diff --git a/src/ops/newoperation.cpp b/src/ops/newoperation.cpp index 89b0be3..28e5804 100644 --- a/src/ops/newoperation.cpp +++ b/src/ops/newoperation.cpp @@ -55,7 +55,7 @@ NewOperation::NewOperation(Device& d, Partition* p) : const FileSystem& fs = newPartition().fileSystem(); - if (fs.type() != FileSystem::Extended) { + if (fs.type() != FileSystem::Type::Extended) { // It would seem tempting to skip the CreateFileSystemJob or the // SetFileSystemLabelJob if either has nothing to do (unformatted FS or // empty label). However, the user might later on decide to change FS or @@ -65,7 +65,7 @@ NewOperation::NewOperation(Device& d, Partition* p) : m_CreateFileSystemJob = new CreateFileSystemJob(targetDevice(), newPartition(), fs.label()); addJob(createFileSystemJob()); - if (fs.type() == FileSystem::Lvm2_PV) { + if (fs.type() == FileSystem::Type::Lvm2_PV) { m_SetPartFlagsJob = new SetPartFlagsJob(targetDevice(), newPartition(), PartitionTable::FlagLvm); addJob(setPartFlagsJob()); } diff --git a/src/ops/removevolumegroupoperation.cpp b/src/ops/removevolumegroupoperation.cpp index c269bbb..b523c83 100644 --- a/src/ops/removevolumegroupoperation.cpp +++ b/src/ops/removevolumegroupoperation.cpp @@ -67,7 +67,7 @@ bool RemoveVolumeGroupOperation::isRemovable(const VolumeManagerDevice* dev) else if (dev->partitionTable()->children().count() > 1) return false; else - if (dev->partitionTable()->children().first()->fileSystem().type() == FileSystem::Unknown) + if (dev->partitionTable()->children().first()->fileSystem().type() == FileSystem::Type::Unknown) return true; } diff --git a/src/ops/restoreoperation.cpp b/src/ops/restoreoperation.cpp index be8c0ab..56af801 100644 --- a/src/ops/restoreoperation.cpp +++ b/src/ops/restoreoperation.cpp @@ -225,7 +225,7 @@ Partition* RestoreOperation::createRestorePartition(const Device& device, Partit return nullptr; const qint64 end = start + fileInfo.size() / device.logicalSize() - 1; - Partition* p = new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Unknown, start, end, device.logicalSize()), start, end, QString()); + Partition* p = new Partition(&parent, device, PartitionRole(r), FileSystemFactory::create(FileSystem::Type::Unknown, start, end, device.logicalSize()), start, end, QString()); p->setState(Partition::StateRestore); return p; diff --git a/src/plugins/dummy/dummybackend.cpp b/src/plugins/dummy/dummybackend.cpp index 30fe534..ae6f938 100644 --- a/src/plugins/dummy/dummybackend.cpp +++ b/src/plugins/dummy/dummybackend.cpp @@ -74,7 +74,7 @@ FileSystem::Type DummyBackend::detectFileSystem(const QString& deviceNode) { Q_UNUSED(deviceNode) - return FileSystem::Unknown; + return FileSystem::Type::Unknown; } QString DummyBackend::readLabel(const QString& deviceNode) const diff --git a/src/plugins/dummy/dummypartitiontable.cpp b/src/plugins/dummy/dummypartitiontable.cpp index 8da9328..90dd93f 100644 --- a/src/plugins/dummy/dummypartitiontable.cpp +++ b/src/plugins/dummy/dummypartitiontable.cpp @@ -96,7 +96,7 @@ FileSystem::Type DummyPartitionTable::detectFileSystemBySector(Report& report, c Q_UNUSED(device) Q_UNUSED(sector) - FileSystem::Type rval = FileSystem::Unknown; + FileSystem::Type rval = FileSystem::Type::Unknown; return rval; } diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index aa103b7..0858a75 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -209,13 +209,13 @@ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartit else if (partitionType == QStringLiteral("21686148-6449-6E6F-744E-656564454649")) activeFlags = PartitionTable::FlagBiosGrub; - FileSystem::Type type = FileSystem::Unknown; + FileSystem::Type type = FileSystem::Type::Unknown; type = detectFileSystem(partitionNode); PartitionRole::Roles r = PartitionRole::Primary; if ( (d.partitionTable()->type() == PartitionTable::msdos || d.partitionTable()->type() == PartitionTable::msdos_sectorbased) && partitionType.toInt() == 5 ) { r = PartitionRole::Extended; - type = FileSystem::Extended; + type = FileSystem::Type::Extended; } // Find an extended partition this partition is in. @@ -233,7 +233,7 @@ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartit QString mountPoint; bool mounted; // sfdisk does not handle LUKS partitions - if (fs->type() == FileSystem::Luks || fs->type() == FileSystem::Luks2) { + if (fs->type() == FileSystem::Type::Luks || fs->type() == FileSystem::Type::Luks2) { r |= PartitionRole::Luks; FS::luks* luksFs = static_cast(fs); luksFs->initLUKS(); @@ -280,7 +280,7 @@ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartit */ void SfdiskBackend::readSectorsUsed(const Device& d, Partition& p, const QString& mountPoint) { - if (!mountPoint.isEmpty() && p.fileSystem().type() != FileSystem::LinuxSwap && p.fileSystem().type() != FileSystem::Lvm2_PV) { + if (!mountPoint.isEmpty() && p.fileSystem().type() != FileSystem::Type::LinuxSwap && p.fileSystem().type() != FileSystem::Type::Lvm2_PV) { const QStorageInfo storage = QStorageInfo(mountPoint); if (p.isMounted() && storage.isValid()) p.fileSystem().setSectorsUsed( (storage.bytesTotal() - storage.bytesFree()) / d.logicalSize()); @@ -291,7 +291,7 @@ void SfdiskBackend::readSectorsUsed(const Device& d, Partition& p, const QString FileSystem::Type SfdiskBackend::detectFileSystem(const QString& partitionPath) { - FileSystem::Type rval = FileSystem::Unknown; + FileSystem::Type rval = FileSystem::Type::Unknown; ExternalCommand udevCommand(QStringLiteral("udevadm"), { QStringLiteral("info"), @@ -314,43 +314,43 @@ FileSystem::Type SfdiskBackend::detectFileSystem(const QString& partitionPath) version = reFileSystemVersion.captured(1); } - if (s == QStringLiteral("ext2")) rval = FileSystem::Ext2; - else if (s == QStringLiteral("ext3")) rval = FileSystem::Ext3; - else if (s.startsWith(QStringLiteral("ext4"))) rval = FileSystem::Ext4; - else if (s == QStringLiteral("swap")) rval = FileSystem::LinuxSwap; - else if (s == QStringLiteral("ntfs-3g")) rval = FileSystem::Ntfs; - else if (s == QStringLiteral("reiserfs")) rval = FileSystem::ReiserFS; - else if (s == QStringLiteral("reiser4")) rval = FileSystem::Reiser4; - else if (s == QStringLiteral("xfs")) rval = FileSystem::Xfs; - else if (s == QStringLiteral("jfs")) rval = FileSystem::Jfs; - else if (s == QStringLiteral("hfs")) rval = FileSystem::Hfs; - else if (s == QStringLiteral("hfsplus")) rval = FileSystem::HfsPlus; - else if (s == QStringLiteral("ufs")) rval = FileSystem::Ufs; + if (s == QStringLiteral("ext2")) rval = FileSystem::Type::Ext2; + else if (s == QStringLiteral("ext3")) rval = FileSystem::Type::Ext3; + else if (s.startsWith(QStringLiteral("ext4"))) rval = FileSystem::Type::Ext4; + else if (s == QStringLiteral("swap")) rval = FileSystem::Type::LinuxSwap; + else if (s == QStringLiteral("ntfs-3g")) rval = FileSystem::Type::Ntfs; + else if (s == QStringLiteral("reiserfs")) rval = FileSystem::Type::ReiserFS; + else if (s == QStringLiteral("reiser4")) rval = FileSystem::Type::Reiser4; + else if (s == QStringLiteral("xfs")) rval = FileSystem::Type::Xfs; + else if (s == QStringLiteral("jfs")) rval = FileSystem::Type::Jfs; + else if (s == QStringLiteral("hfs")) rval = FileSystem::Type::Hfs; + else if (s == QStringLiteral("hfsplus")) rval = FileSystem::Type::HfsPlus; + else if (s == QStringLiteral("ufs")) rval = FileSystem::Type::Ufs; else if (s == QStringLiteral("vfat")) { if (version == QStringLiteral("FAT32")) - rval = FileSystem::Fat32; + rval = FileSystem::Type::Fat32; else if (version == QStringLiteral("FAT16")) - rval = FileSystem::Fat16; + rval = FileSystem::Type::Fat16; else if (version == QStringLiteral("FAT12")) - rval = FileSystem::Fat12; + rval = FileSystem::Type::Fat12; } - else if (s == QStringLiteral("btrfs")) rval = FileSystem::Btrfs; - else if (s == QStringLiteral("ocfs2")) rval = FileSystem::Ocfs2; - else if (s == QStringLiteral("zfs_member")) rval = FileSystem::Zfs; - else if (s == QStringLiteral("hpfs")) rval = FileSystem::Hpfs; + else if (s == QStringLiteral("btrfs")) rval = FileSystem::Type::Btrfs; + else if (s == QStringLiteral("ocfs2")) rval = FileSystem::Type::Ocfs2; + else if (s == QStringLiteral("zfs_member")) rval = FileSystem::Type::Zfs; + else if (s == QStringLiteral("hpfs")) rval = FileSystem::Type::Hpfs; else if (s == QStringLiteral("crypto_LUKS")) { if (version == QStringLiteral("1")) - rval = FileSystem::Luks; + rval = FileSystem::Type::Luks; else if (version == QStringLiteral("2")) { - rval = FileSystem::Luks2; + rval = FileSystem::Type::Luks2; } } - else if (s == QStringLiteral("exfat")) rval = FileSystem::Exfat; - else if (s == QStringLiteral("nilfs2")) rval = FileSystem::Nilfs2; - else if (s == QStringLiteral("LVM2_member")) rval = FileSystem::Lvm2_PV; - else if (s == QStringLiteral("f2fs")) rval = FileSystem::F2fs; - else if (s == QStringLiteral("udf")) rval = FileSystem::Udf; - else if (s == QStringLiteral("iso9660")) rval = FileSystem::Iso9660; + else if (s == QStringLiteral("exfat")) rval = FileSystem::Type::Exfat; + else if (s == QStringLiteral("nilfs2")) rval = FileSystem::Type::Nilfs2; + else if (s == QStringLiteral("LVM2_member")) rval = FileSystem::Type::Lvm2_PV; + else if (s == QStringLiteral("f2fs")) rval = FileSystem::Type::F2fs; + else if (s == QStringLiteral("udf")) rval = FileSystem::Type::Udf; + else if (s == QStringLiteral("iso9660")) rval = FileSystem::Type::Iso9660; else qWarning() << "unknown file system type " << s << " on " << partitionPath; } diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 79c2a55..9124107 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -135,7 +135,7 @@ bool SfdiskPartitionTable::resizeFileSystem(Report& report, const Partition& par FileSystem::Type SfdiskPartitionTable::detectFileSystemBySector(Report& report, const Device& device, qint64 sector) { - FileSystem::Type type = FileSystem::Unknown; + FileSystem::Type type = FileSystem::Type::Unknown; ExternalCommand jsonCommand(QStringLiteral("sfdisk"), { QStringLiteral("--json"), device.deviceNode() } ); if (jsonCommand.run(-1) && jsonCommand.exitCode() == 0) { @@ -160,24 +160,24 @@ static struct { FileSystem::Type type; QLatin1String partitionType[2]; // GPT, MBR } typemap[] = { - { FileSystem::Btrfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Ext2, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Ext3, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Ext4, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::LinuxSwap, { QLatin1String("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F"), QLatin1String("82") } }, - { FileSystem::Fat12, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("6") } }, - { FileSystem::Fat16, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("6") } }, - { FileSystem::Fat32, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, - { FileSystem::Nilfs2, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Ntfs, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, - { FileSystem::Exfat, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, - { FileSystem::ReiserFS, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Reiser4, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Xfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Jfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, - { FileSystem::Hfs, { QLatin1String("48465300-0000-11AA-AA11-00306543ECAC"), QLatin1String("af")} }, - { FileSystem::HfsPlus, { QLatin1String("48465300-0000-11AA-AA11-00306543ECAC"), QLatin1String("af") } }, - { FileSystem::Udf, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } } + { FileSystem::Type::Btrfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Ext2, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Ext3, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Ext4, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::LinuxSwap, { QLatin1String("0657FD6D-A4AB-43C4-84E5-0933C84B4F4F"), QLatin1String("82") } }, + { FileSystem::Type::Fat12, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("6") } }, + { FileSystem::Type::Fat16, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("6") } }, + { FileSystem::Type::Fat32, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, + { FileSystem::Type::Nilfs2, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Ntfs, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, + { FileSystem::Type::Exfat, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } }, + { FileSystem::Type::ReiserFS, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Reiser4, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Xfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Jfs, { QLatin1String("0FC63DAF-8483-4772-8E79-3D69D8477DE4"), QLatin1String("83") } }, + { FileSystem::Type::Hfs, { QLatin1String("48465300-0000-11AA-AA11-00306543ECAC"), QLatin1String("af")} }, + { FileSystem::Type::HfsPlus, { QLatin1String("48465300-0000-11AA-AA11-00306543ECAC"), QLatin1String("af") } }, + { FileSystem::Type::Udf, { QLatin1String("EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"), QLatin1String("7") } } // Add ZFS too }; From 2e5f0fbcb26e9faa8fc23fff4b59ee7de78d14f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 8 Apr 2018 01:46:08 +0100 Subject: [PATCH 077/175] d-pointerize FileSystem class. --- src/fs/filesystem.cpp | 99 ++++++++++++++++++++++++++++++++++++++----- src/fs/filesystem.h | 92 +++++++++++++++++++--------------------- 2 files changed, 132 insertions(+), 59 deletions(-) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 9dc6c77..0919294 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -1,7 +1,7 @@ /************************************************************************* * Copyright (C) 2012 by Volker Lanz * * Copyright (C) 2015 by Teo Mrnjavac * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -72,21 +72,35 @@ const std::vector FileSystem::defaultColorCode = } }; +struct FileSystemPrivate { + FileSystem::Type m_Type; + qint64 m_FirstSector; + qint64 m_LastSector; + qint64 m_SectorSize; + qint64 m_SectorsUsed; + QString m_Label; + QString m_UUID; +}; /** Creates a new FileSystem object @param firstsector the first sector used by this FileSystem on the Device @param lastsector the last sector used by this FileSystem on the Device @param sectorsused the number of sectors in use on the FileSystem - @param l the FileSystem label - @param t the FileSystem type + @param label the FileSystem label + @param type the FileSystem type */ -FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& l, FileSystem::Type t) : - m_Type(t), - m_FirstSector(firstsector), - m_LastSector(lastsector), - m_SectorsUsed(sectorsused), - m_Label(l), - m_UUID() +FileSystem::FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) : + d(std::make_unique()) +{ + d->m_Type = type; + d->m_FirstSector = firstsector; + d->m_LastSector = lastsector; + d->m_SectorsUsed = sectorsused; + d->m_Label = label; + d->m_UUID = QString(); +} + +FileSystem::~FileSystem() { } @@ -392,6 +406,11 @@ QString FileSystem::name(const QStringList& languages) const return nameForType(type(), languages); } +FileSystem::Type FileSystem::type() const +{ + return d->m_Type; +} + /** @return a pointer to a QString C array with all FileSystem names */ static const KLocalizedString* typeNames() { @@ -530,6 +549,16 @@ bool FileSystem::unmount(Report& report, const QString& deviceNode) return false; } +qint64 FileSystem::firstSector() const +{ + return d->m_FirstSector; +} + +qint64 FileSystem::lastSector() const +{ + return d->m_LastSector; +} + bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode) { QString cmdFullPath = QStandardPaths::findExecutable(cmdName); @@ -552,3 +581,53 @@ FileSystem::SupportTool FileSystem::supportToolName() const { return SupportTool(); } + +void FileSystem::setFirstSector(qint64 s) +{ + d->m_FirstSector = s; +} + +void FileSystem::setLastSector(qint64 s) +{ + d->m_LastSector = s; +} + +const QString& FileSystem::label() const +{ + return d->m_Label; +} + +qint64 FileSystem::sectorSize() const +{ + return d->m_SectorSize; +} + +qint64 FileSystem::sectorsUsed() const +{ + return d->m_SectorsUsed; +} + +const QString& FileSystem::uuid() const +{ + return d->m_UUID; +} + +void FileSystem::setSectorSize(qint64 s) +{ + d->m_SectorSize = s; +} + +void FileSystem::setSectorsUsed(qint64 s) +{ + d->m_SectorsUsed = s; +} + +void FileSystem::setLabel(const QString& s) +{ + d->m_Label = s; +} + +void FileSystem::setUUID(const QString& s) +{ + d->m_UUID = s; +} diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index fc63463..110107a 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -28,12 +28,14 @@ #include #include +#include #include class QColor; class QValidator; class Device; class Report; +struct FileSystemPrivate; /** Base class for all FileSystems. @@ -106,10 +108,10 @@ public: Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType) protected: - FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t); + FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type); public: - virtual ~FileSystem() {} + virtual ~FileSystem(); public: virtual void init() {} @@ -196,9 +198,11 @@ public: * @see nameForType() */ virtual QString name(const QStringList& languages = {}) const; - virtual FileSystem::Type type() const { - return m_Type; /**< @return the FileSystem's type */ - } + + /** + * @return the FileSystem's type + */ + virtual FileSystem::Type type() const; /** * Returns the name of the given filesystem type. If @p languages @@ -228,12 +232,12 @@ public: virtual bool mount(Report& report, const QString& deviceNode, const QString& mountPoint); virtual bool unmount(Report& report, const QString& deviceNode); - qint64 firstSector() const { - return m_FirstSector; /**< @return the FileSystem's first sector */ - } - qint64 lastSector() const { - return m_LastSector; /**< @return the FileSystem's last sector */ - } + /**< @return the FileSystem's first sector */ + qint64 firstSector() const; + + /**< @return the FileSystem's last sector */ + qint64 lastSector() const; + qint64 length() const { return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */ } @@ -244,52 +248,42 @@ public: return firstByte() + length() * sectorSize() - 1; /**< @return the FileSystem's last byte */ } - void setFirstSector(qint64 s) { - m_FirstSector = s; /**< @param s the new first sector */ - } - void setLastSector(qint64 s) { - m_LastSector = s; /**< @param s the new last sector */ - } + /**< @param s the new first sector */ + void setFirstSector(qint64 s); + + /**< @param s the new last sector */ + void setLastSector(qint64 s); void move(qint64 newStartSector); - const QString& label() const { - return m_Label; /**< @return the FileSystem's label */ - } - qint64 sectorSize() const { - return m_SectorSize; /**< @return the sector size in the underlying Device */ - } - qint64 sectorsUsed() const { - return m_SectorsUsed; /**< @return the sectors in use on the FileSystem */ - } - const QString& uuid() const { - return m_UUID; /**< @return the FileSystem's UUID */ - } + /**< @return the FileSystem's label */ + const QString& label() const; - void setSectorSize(qint64 s) { - m_SectorSize = s; /**< @param s the new value for sector size */ - } - void setSectorsUsed(qint64 s) { - m_SectorsUsed = s; /**< @param s the new value for sectors in use */ - } - void setLabel(const QString& s) { - m_Label = s; /**< @param s the new label */ - } - void setUUID(const QString& s) { - m_UUID = s; /**< @param s the new UUID */ - } + /**< @return the sector size in the underlying Device */ + qint64 sectorSize() const; + + /**< @return the sectors in use on the FileSystem */ + qint64 sectorsUsed() const; + + /**< @return the FileSystem's UUID */ + const QString& uuid() const; + + /**< @param s the new value for sector size */ + void setSectorSize(qint64 s); + + /**< @param s the new value for sectors in use */ + void setSectorsUsed(qint64 s); + + /**< @param s the new label */ + void setLabel(const QString& s); + + /**< @param s the new UUID */ + void setUUID(const QString& s); protected: static bool findExternal(const QString& cmdName, const QStringList& args = QStringList(), int exptectedCode = 1); -protected: - FileSystem::Type m_Type; - qint64 m_FirstSector; - qint64 m_LastSector; - qint64 m_SectorSize; - qint64 m_SectorsUsed; - QString m_Label; - QString m_UUID; + std::unique_ptr d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(FileSystem::CommandSupportTypes) From a71be700ba9e103e294cbd014ce27f98b34a9a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 8 Apr 2018 14:45:59 +0100 Subject: [PATCH 078/175] d-pointerize Device class. --- src/core/device.cpp | 118 ++++++++++++++++++++++++------- src/core/device.h | 84 ++++++++-------------- src/core/device_p.h | 35 +++++++++ src/core/volumemanagerdevice.cpp | 8 +++ src/core/volumemanagerdevice.h | 10 +-- 5 files changed, 168 insertions(+), 87 deletions(-) create mode 100644 src/core/device_p.h diff --git a/src/core/device.cpp b/src/core/device.cpp index 7e2c4a5..2db86df 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -17,6 +17,7 @@ *************************************************************************/ #include "core/device.h" +#include "core/device_p.h" #include "core/partitiontable.h" #include "core/smartstatus.h" @@ -30,20 +31,21 @@ */ Device::Device(const QString& name, const QString& deviceNode, - const qint64 logicalSize, - const qint64 totalLogical, + const qint64 logicalSectorSize, + const qint64 totalLogicalSectors, const QString& iconName, Device::Type type) : QObject() - , m_Name(name.length() > 0 ? name : i18n("Unknown Device")) - , m_DeviceNode(deviceNode) - , m_LogicalSize(logicalSize) - , m_TotalLogical(totalLogical) - , m_PartitionTable(nullptr) - , m_IconName(iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName) - , m_SmartStatus(type == Device::Disk_Device ? new SmartStatus(deviceNode) : nullptr) - , m_Type(type) + , d(std::make_shared()) { + d->m_Name = name.length() > 0 ? name : i18n("Unknown Device"); + d->m_DeviceNode = deviceNode; + d->m_LogicalSectorSize = logicalSectorSize; + d->m_TotalLogical = totalLogicalSectors; + d->m_PartitionTable = nullptr; + d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; + d->m_SmartStatus = type == Device::Disk_Device ? new SmartStatus(deviceNode) : nullptr; + d->m_Type = type; } /** Copy constructor for Device. @@ -51,30 +53,31 @@ Device::Device(const QString& name, */ Device::Device(const Device& other) : QObject() - , m_Name(other.m_Name) - , m_DeviceNode(other.m_DeviceNode) - , m_LogicalSize(other.m_LogicalSize) - , m_TotalLogical(other.m_TotalLogical) - , m_PartitionTable(nullptr) - , m_IconName(other.m_IconName) - , m_SmartStatus(nullptr) - , m_Type(other.m_Type) { - if (other.m_PartitionTable) - m_PartitionTable = new PartitionTable(*other.m_PartitionTable); - if (other.m_SmartStatus) - m_SmartStatus = new SmartStatus(*other.m_SmartStatus); + d->m_Name = other.d->m_Name; + d->m_DeviceNode = other.d->m_DeviceNode; + d->m_LogicalSectorSize = other.d->m_LogicalSectorSize; + d->m_TotalLogical = other.d->m_TotalLogical; + d->m_PartitionTable = nullptr; + d->m_IconName = other.d->m_IconName; + d->m_SmartStatus = nullptr; + d->m_Type = other.d->m_Type; + + if (other.d->m_PartitionTable) + d->m_PartitionTable = new PartitionTable(*other.d->m_PartitionTable); + if (other.d->m_SmartStatus) + d->m_SmartStatus = new SmartStatus(*other.d->m_SmartStatus); } /** Destructs a Device. */ Device::~Device() { - delete m_PartitionTable; + delete d->m_PartitionTable; } bool Device::operator==(const Device& other) const { - return m_DeviceNode == other.m_DeviceNode; + return d->m_DeviceNode == other.d->m_DeviceNode; } bool Device::operator!=(const Device& other) const @@ -86,3 +89,68 @@ QString Device::prettyName() const { return xi18nc("@item:inlistbox Device name – Capacity (device node)", "%1 – %2 (%3)", name(), Capacity::formatByteSize(capacity()), deviceNode()); } + +QString& Device::name() +{ + return d->m_Name; +} + +const QString& Device::name() const +{ + return d->m_Name; +} + +const QString& Device::deviceNode() const +{ + return d->m_DeviceNode; +} + +qint64 Device::logicalSize() const +{ + return d->m_LogicalSectorSize; +} + +qint64 Device::totalLogical() const +{ + return d->m_TotalLogical; +} + +PartitionTable* Device::partitionTable() +{ + return d->m_PartitionTable; +} + +const PartitionTable* Device::partitionTable() const +{ + return d->m_PartitionTable; +} + +void Device::setPartitionTable(PartitionTable* ptable) +{ + d->m_PartitionTable = ptable; +} + +const QString& Device::iconName() const +{ + return d->m_IconName; +} + +void Device::setIconName(const QString& name) +{ + d->m_IconName = name; +} + +SmartStatus& Device::smartStatus() +{ + return *(d->m_SmartStatus); +} + +const SmartStatus& Device::smartStatus() const +{ + return *(d->m_SmartStatus); +} + +Device::Type Device::type() const +{ + return d->m_Type; +} diff --git a/src/core/device.h b/src/core/device.h index db7c391..a628f34 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -23,10 +23,13 @@ #include #include +#include + class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; +struct DevicePrivate; /** A device description. @@ -55,7 +58,7 @@ public: }; protected: - explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); + explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); public: explicit Device(const Device& other); @@ -65,78 +68,49 @@ public: virtual bool operator==(const Device& other) const; virtual bool operator!=(const Device& other) const; - virtual QString& name() { - return m_Name; /**< @return the Device's name, usually some manufacturer string */ - } + /**< @return the Device's name, usually some manufacturer string */ + virtual QString& name(); + virtual const QString& name() const; - virtual const QString& name() const { - return m_Name; /**< @return the Device's name, usually some manufacturer string */ - } + /**< @return the Device's node, for example "/dev/sda" */ + virtual const QString& deviceNode() const; - virtual const QString& deviceNode() const { - return m_DeviceNode; /**< @return the Device's node, for example "/dev/sda" */ - } + /**< @return the logical sector size the Device uses (would be extent size for e.g. LVM devices) */ + virtual qint64 logicalSize() const; - virtual PartitionTable* partitionTable() { - return m_PartitionTable; /**< @return the Device's PartitionTable */ - } + /**< @return the total number of logical sectors on the device */ + virtual qint64 totalLogical() const; - virtual const PartitionTable* partitionTable() const { - return m_PartitionTable; /**< @return the Device's PartitionTable */ - } - - virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */ - return logicalSize() * totalLogical(); - } - - virtual void setIconName(const QString& name) { - m_IconName = name; - } - - virtual const QString& iconName() const { - return m_IconName; /**< @return suggested icon name for this Device */ - } - - virtual SmartStatus& smartStatus() { - return *m_SmartStatus; - } - - virtual const SmartStatus& smartStatus() const { - return *m_SmartStatus; - } + /**< @return the Device's PartitionTable */ + virtual PartitionTable* partitionTable(); + virtual const PartitionTable* partitionTable() const; /** * Change the description of the partition table for different one. * The device itself is not changed; use CreatePartitionTableOperation * for that. The Device instance becomes the owner of @p ptable . */ - virtual void setPartitionTable(PartitionTable* ptable) { - m_PartitionTable = ptable; + virtual void setPartitionTable(PartitionTable* ptable); + + virtual qint64 capacity() const { /**< @return the Device's capacity in bytes */ + return logicalSize() * totalLogical(); } - virtual qint64 logicalSize() const { - return m_LogicalSize; - } + /**< @return suggested icon name for this Device */ + virtual const QString& iconName() const; - virtual qint64 totalLogical() const { - return m_TotalLogical; - } + /**< @param name set the new Icon for this Device */ + virtual void setIconName(const QString& name); - virtual Device::Type type() const { - return m_Type; - } + virtual SmartStatus& smartStatus(); + virtual const SmartStatus& smartStatus() const; + + virtual Device::Type type() const; virtual QString prettyName() const; protected: - QString m_Name; - QString m_DeviceNode; - qint64 m_LogicalSize; - qint64 m_TotalLogical; - PartitionTable* m_PartitionTable; - QString m_IconName; - SmartStatus* m_SmartStatus; - Device::Type m_Type; + std::shared_ptr d; }; #endif diff --git a/src/core/device_p.h b/src/core/device_p.h new file mode 100644 index 0000000..5ddab62 --- /dev/null +++ b/src/core/device_p.h @@ -0,0 +1,35 @@ +/************************************************************************* + * Copyright (C) 2018 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "core/device.h" + +#include + +class PartitionTable; +class SmartStatus; + +struct DevicePrivate +{ + QString m_Name; + QString m_DeviceNode; + qint64 m_LogicalSectorSize; + qint64 m_TotalLogical; + PartitionTable* m_PartitionTable; + QString m_IconName; + SmartStatus* m_SmartStatus; + Device::Type m_Type; +}; diff --git a/src/core/volumemanagerdevice.cpp b/src/core/volumemanagerdevice.cpp index 8c996cf..8dc9659 100644 --- a/src/core/volumemanagerdevice.cpp +++ b/src/core/volumemanagerdevice.cpp @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * + * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -15,6 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ +#include "core/device_p.h" #include "core/volumemanagerdevice.h" /** Constructs an abstract Volume Manager Device with an empty PartitionTable. @@ -34,3 +36,9 @@ QString VolumeManagerDevice::prettyDeviceNodeList() const { return deviceNodes().join(QStringLiteral(", ")); } + +void VolumeManagerDevice::setTotalLogical(qint64 n) +{ + Q_ASSERT(n > 0); + d->m_TotalLogical = n; +} diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index 42c84c8..be59eb5 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_VOLUMEMANAGERDEVICE_H) - +#ifndef KPMCORE_VOLUMEMANAGERDEVICE_H #define KPMCORE_VOLUMEMANAGERDEVICE_H #include "util/libpartitionmanagerexport.h" @@ -76,7 +75,7 @@ protected: * @sector sector value to be mapped (if 0, will return start sector of the partition) * @return absolute sector value as represented inside device's partitionTable */ - virtual qint64 mappedSector(const QString& partitionPath, qint64 sector) const = 0; + virtual qint64 mappedSector(const QString& partitionPath, qint64 sector) const = 0; public: @@ -90,10 +89,7 @@ public: * * @param n Number of sectors. */ - void setTotalLogical(qint64 n) { - Q_ASSERT(n > 0); - m_TotalLogical = n; - } + void setTotalLogical(qint64 n); }; #endif From 210dea15de6502d56945dfd0c4114219a4ffd71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 8 Apr 2018 14:58:02 +0100 Subject: [PATCH 079/175] Use smart pointer for SmartStatus. Fixes a memory leak. --- src/core/device.cpp | 5 ++--- src/core/device_p.h | 4 +++- src/core/smartstatus.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/core/device.cpp b/src/core/device.cpp index 2db86df..b52177c 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -44,7 +44,7 @@ Device::Device(const QString& name, d->m_TotalLogical = totalLogicalSectors; d->m_PartitionTable = nullptr; d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; - d->m_SmartStatus = type == Device::Disk_Device ? new SmartStatus(deviceNode) : nullptr; + d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; d->m_Type = type; } @@ -62,11 +62,10 @@ Device::Device(const Device& other) d->m_IconName = other.d->m_IconName; d->m_SmartStatus = nullptr; d->m_Type = other.d->m_Type; + d->m_SmartStatus = other.d->m_SmartStatus; if (other.d->m_PartitionTable) d->m_PartitionTable = new PartitionTable(*other.d->m_PartitionTable); - if (other.d->m_SmartStatus) - d->m_SmartStatus = new SmartStatus(*other.d->m_SmartStatus); } /** Destructs a Device. */ diff --git a/src/core/device_p.h b/src/core/device_p.h index 5ddab62..0577fe3 100644 --- a/src/core/device_p.h +++ b/src/core/device_p.h @@ -19,6 +19,8 @@ #include +#include + class PartitionTable; class SmartStatus; @@ -30,6 +32,6 @@ struct DevicePrivate qint64 m_TotalLogical; PartitionTable* m_PartitionTable; QString m_IconName; - SmartStatus* m_SmartStatus; + std::shared_ptr m_SmartStatus; Device::Type m_Type; }; diff --git a/src/core/smartstatus.h b/src/core/smartstatus.h index d064b7e..88b410d 100644 --- a/src/core/smartstatus.h +++ b/src/core/smartstatus.h @@ -121,7 +121,7 @@ public: static QString overallAssessmentToString(Overall o); static QString selfTestStatusToString(SmartStatus::SelfTestStatus s); -protected: +private: void setStatus(bool s) { m_Status = s; From df364bdc7cce5a87d327b71bec26c3ead018387f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 00:34:45 +0100 Subject: [PATCH 080/175] Reuse the d-pointer of the base class Device for the child class DiskDevice. --- src/core/device.cpp | 24 ++++++++++++++++++++++++ src/core/device.h | 5 +++-- src/core/device_p.h | 3 ++- src/core/diskdevice.cpp | 34 +++++++++++++++++++--------------- src/core/diskdevice.h | 5 +---- 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/core/device.cpp b/src/core/device.cpp index b52177c..f6acae1 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -48,6 +48,30 @@ Device::Device(const QString& name, d->m_Type = type; } +/** Constructs a Device with an empty PartitionTable. + @param name the Device's name, usually some string defined by the manufacturer + @param deviceNode the Device's node, for example "/dev/sda" +*/ +Device::Device(std::shared_ptr d_ptr, + const QString& name, + const QString& deviceNode, + const qint64 logicalSectorSize, + const qint64 totalLogicalSectors, + const QString& iconName, + Device::Type type) + : QObject() + , d(d_ptr) +{ + d->m_Name = name.length() > 0 ? name : i18n("Unknown Device"); + d->m_DeviceNode = deviceNode; + d->m_LogicalSectorSize = logicalSectorSize; + d->m_TotalLogical = totalLogicalSectors; + d->m_PartitionTable = nullptr; + d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; + d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; + d->m_Type = type; +} + /** Copy constructor for Device. * @param other the other Device. */ diff --git a/src/core/device.h b/src/core/device.h index a628f34..393723a 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -29,7 +29,7 @@ class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; -struct DevicePrivate; +class DevicePrivate; /** A device description. @@ -60,11 +60,12 @@ public: protected: explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); + explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); + public: explicit Device(const Device& other); virtual ~Device(); -public: virtual bool operator==(const Device& other) const; virtual bool operator!=(const Device& other) const; diff --git a/src/core/device_p.h b/src/core/device_p.h index 0577fe3..688f3c5 100644 --- a/src/core/device_p.h +++ b/src/core/device_p.h @@ -24,8 +24,9 @@ class PartitionTable; class SmartStatus; -struct DevicePrivate +class DevicePrivate { +public: QString m_Name; QString m_DeviceNode; qint64 m_LogicalSectorSize; diff --git a/src/core/diskdevice.cpp b/src/core/diskdevice.cpp index 6a1cdee..c23cb58 100644 --- a/src/core/diskdevice.cpp +++ b/src/core/diskdevice.cpp @@ -17,6 +17,7 @@ *************************************************************************/ #include "core/diskdevice.h" +#include "core/device_p.h" #include "core/partitiontable.h" #include "core/smartstatus.h" @@ -39,7 +40,11 @@ #define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */ #endif -struct DiskDevicePrivate { +#define d_ptr std::static_pointer_cast(d) + +class DiskDevicePrivate : public DevicePrivate +{ +public: qint32 m_Heads; qint32 m_SectorsPerTrack; qint32 m_Cylinders; @@ -94,47 +99,46 @@ DiskDevice::DiskDevice(const QString& name, qint32 cylinders, qint64 sectorSize, const QString& iconName) - : Device(name, deviceNode, sectorSize, (static_cast(heads) * cylinders * numSectors), iconName, Device::Disk_Device) - , d(std::make_unique()) + : Device(std::make_shared(), name, deviceNode, sectorSize, (static_cast(heads) * cylinders * numSectors), iconName, Device::Disk_Device) { - d->m_Heads = heads; - d->m_SectorsPerTrack = numSectors; - d->m_Cylinders = cylinders; - d->m_LogicalSectorSize = sectorSize; - d->m_PhysicalSectorSize = getPhysicalSectorSize(deviceNode); + d_ptr->m_Heads = heads; + d_ptr->m_SectorsPerTrack = numSectors; + d_ptr->m_Cylinders = cylinders; + d_ptr->m_LogicalSectorSize = sectorSize; + d_ptr->m_PhysicalSectorSize = getPhysicalSectorSize(deviceNode); } qint32 DiskDevice::heads() const { - return d->m_Heads; + return d_ptr->m_Heads; } qint32 DiskDevice::cylinders() const { - return d->m_Cylinders; + return d_ptr->m_Cylinders; } qint32 DiskDevice::sectorsPerTrack() const { - return d->m_SectorsPerTrack; + return d_ptr->m_SectorsPerTrack; } qint64 DiskDevice::physicalSectorSize() const { - return d->m_PhysicalSectorSize; + return d_ptr->m_PhysicalSectorSize; } qint64 DiskDevice::logicalSectorSize() const { - return d->m_LogicalSectorSize; + return d_ptr->m_LogicalSectorSize; } qint64 DiskDevice::totalSectors() const { - return static_cast(d->m_Heads) * d->m_Cylinders * d->m_SectorsPerTrack; + return static_cast(d_ptr->m_Heads) * d_ptr->m_Cylinders * d_ptr->m_SectorsPerTrack; } qint64 DiskDevice::cylinderSize() const { - return static_cast(d->m_Heads) * d->m_SectorsPerTrack; + return static_cast(d_ptr->m_Heads) * d_ptr->m_SectorsPerTrack; } diff --git a/src/core/diskdevice.h b/src/core/diskdevice.h index 5b5013c..1205b88 100644 --- a/src/core/diskdevice.h +++ b/src/core/diskdevice.h @@ -32,7 +32,7 @@ class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; -struct DiskDevicePrivate; +class DiskDevicePrivate; /** A disk device. @@ -91,9 +91,6 @@ public: * @return the size of a cylinder on this Device in sectors */ qint64 cylinderSize() const; - -private: - std::unique_ptr d; }; #endif From 7e8bab3b4e07dd10f3d671b6a18c544343c38f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 02:40:24 +0100 Subject: [PATCH 081/175] d-pointerize LvmDevice class. --- src/core/device.cpp | 23 --------- src/core/device.h | 2 - src/core/device_p.h | 5 ++ src/core/lvmdevice.cpp | 83 ++++++++++++++++++++++++++++---- src/core/lvmdevice.h | 53 ++++---------------- src/core/volumemanagerdevice.cpp | 11 +++-- src/core/volumemanagerdevice.h | 5 +- src/core/volumemanagerdevice_p.h | 27 +++++++++++ 8 files changed, 126 insertions(+), 83 deletions(-) create mode 100644 src/core/volumemanagerdevice_p.h diff --git a/src/core/device.cpp b/src/core/device.cpp index f6acae1..d6f576c 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -25,29 +25,6 @@ #include -/** Constructs a Device with an empty PartitionTable. - @param name the Device's name, usually some string defined by the manufacturer - @param deviceNode the Device's node, for example "/dev/sda" -*/ -Device::Device(const QString& name, - const QString& deviceNode, - const qint64 logicalSectorSize, - const qint64 totalLogicalSectors, - const QString& iconName, - Device::Type type) - : QObject() - , d(std::make_shared()) -{ - d->m_Name = name.length() > 0 ? name : i18n("Unknown Device"); - d->m_DeviceNode = deviceNode; - d->m_LogicalSectorSize = logicalSectorSize; - d->m_TotalLogical = totalLogicalSectors; - d->m_PartitionTable = nullptr; - d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; - d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; - d->m_Type = type; -} - /** Constructs a Device with an empty PartitionTable. @param name the Device's name, usually some string defined by the manufacturer @param deviceNode the Device's node, for example "/dev/sda" diff --git a/src/core/device.h b/src/core/device.h index 393723a..f99e642 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -58,8 +58,6 @@ public: }; protected: - explicit Device(const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); - explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); public: diff --git a/src/core/device_p.h b/src/core/device_p.h index 688f3c5..97d152c 100644 --- a/src/core/device_p.h +++ b/src/core/device_p.h @@ -15,6 +15,9 @@ * along with this program. If not, see .* *************************************************************************/ +#ifndef KPMCORE_DEVICE_P_H +#define KPMCORE_DEVICE_P_H + #include "core/device.h" #include @@ -36,3 +39,5 @@ public: std::shared_ptr m_SmartStatus; Device::Type m_Type; }; + +#endif diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 0799c54..917410c 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -18,6 +18,7 @@ #include "core/lvmdevice.h" #include "core/partition.h" +#include "core/volumemanagerdevice_p.h" #include "fs/filesystem.h" #include "fs/lvm2_pv.h" #include "fs/luks.h" @@ -34,26 +35,43 @@ #include +#define d_ptr std::static_pointer_cast(d) + +class LvmDevicePrivate : public VolumeManagerDevicePrivate +{ +public: + qint64 m_peSize; + qint64 m_totalPE; + qint64 m_allocPE; + qint64 m_freePE; + QString m_UUID; + + mutable QStringList* m_LVPathList; + QVector m_PVs; + mutable QHash* m_LVSizeMap; +}; + /** Constructs a representation of LVM device with initialized LV as Partitions * * @param vgName Volume Group name * @param iconName Icon representing LVM Volume group */ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName) - : VolumeManagerDevice(vgName, + : VolumeManagerDevice(std::make_shared(), + vgName, (QStringLiteral("/dev/") + vgName), getPeSize(vgName), getTotalPE(vgName), iconName, Device::LVM_Device) { - m_peSize = logicalSize(); - m_totalPE = totalLogical(); - m_freePE = getFreePE(vgName); - m_allocPE = m_totalPE - m_freePE; - m_UUID = getUUID(vgName); - m_LVPathList = new QStringList(getLVs(vgName)); - m_LVSizeMap = new QHash(); + d_ptr->m_peSize = logicalSize(); + d_ptr->m_totalPE = totalLogical(); + d_ptr->m_freePE = getFreePE(vgName); + d_ptr->m_allocPE = d_ptr->m_totalPE - d_ptr->m_freePE; + d_ptr->m_UUID = getUUID(vgName); + d_ptr->m_LVPathList = new QStringList(getLVs(vgName)); + d_ptr->m_LVSizeMap = new QHash(); initPartitions(); } @@ -66,8 +84,8 @@ QVector LvmDevice::s_DirtyPVs; LvmDevice::~LvmDevice() { - delete m_LVPathList; - delete m_LVSizeMap; + delete d_ptr->m_LVPathList; + delete d_ptr->m_LVSizeMap; } void LvmDevice::initPartitions() @@ -492,3 +510,48 @@ bool LvmDevice::activateLV(const QString& lvPath) lvPath }); return deactivate.run(-1) && deactivate.exitCode() == 0; } + +qint64 LvmDevice::peSize() const +{ + return d_ptr->m_peSize; +} + +qint64 LvmDevice::totalPE() const +{ + return d_ptr->m_totalPE; +} + +qint64 LvmDevice::allocatedPE() const +{ + return d_ptr->m_allocPE; +} + +qint64 LvmDevice::freePE() const +{ + return d_ptr->m_freePE; +} + +QString LvmDevice::UUID() const +{ + return d_ptr->m_UUID; +} + +QStringList* LvmDevice::LVPathList() const +{ + return d_ptr->m_LVPathList; +} + +QVector & LvmDevice::physicalVolumes() +{ + return d_ptr->m_PVs; +} + +const QVector & LvmDevice::physicalVolumes() const +{ + return d_ptr->m_PVs; +} + +QHash* LvmDevice::LVSizeMap() const +{ + return d_ptr->m_LVSizeMap; +} diff --git a/src/core/lvmdevice.h b/src/core/lvmdevice.h index 8a49263..08b768e 100644 --- a/src/core/lvmdevice.h +++ b/src/core/lvmdevice.h @@ -16,8 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_LVMDEVICE_H) - +#ifndef KPMCORE_LVMDEVICE_H #define KPMCORE_LVMDEVICE_H #include "core/device.h" @@ -57,7 +56,6 @@ public: static QVector s_DirtyPVs; -public: static void scanSystemLVM(QList& devices); static const QStringList getVGs(); @@ -89,54 +87,23 @@ public: static bool activateVG(Report& report, const LvmDevice& d); protected: - void initPartitions() override; const QList scanPartitions(PartitionTable* pTable) const; Partition* scanPartition(const QString& lvPath, PartitionTable* pTable) const; qint64 mappedSector(const QString& lvPath, qint64 sector) const override; public: - qint64 peSize() const { - return m_peSize; - } - qint64 totalPE() const { - return m_totalPE; - } - qint64 allocatedPE() const { - return m_allocPE; - } - qint64 freePE() const { - return m_freePE; - } - QString UUID() const { - return m_UUID; - } - QStringList* LVPathList() const { - return m_LVPathList; - } - QVector & physicalVolumes() { - return m_PVs; - } - const QVector & physicalVolumes() const { - return m_PVs; - } + qint64 peSize() const; + qint64 totalPE() const; + qint64 allocatedPE() const; + qint64 freePE() const; + QString UUID() const; + QStringList* LVPathList() const; + QVector & physicalVolumes(); + const QVector & physicalVolumes() const; protected: - QHash* LVSizeMap() const { - return m_LVSizeMap; - } - -private: - qint64 m_peSize; - qint64 m_totalPE; - qint64 m_allocPE; - qint64 m_freePE; - QString m_UUID; - - mutable QStringList* m_LVPathList; - QVector m_PVs; - mutable QHash* m_LVSizeMap; - + QHash* LVSizeMap() const; }; #endif diff --git a/src/core/volumemanagerdevice.cpp b/src/core/volumemanagerdevice.cpp index 8dc9659..7c339af 100644 --- a/src/core/volumemanagerdevice.cpp +++ b/src/core/volumemanagerdevice.cpp @@ -18,17 +18,22 @@ #include "core/device_p.h" #include "core/volumemanagerdevice.h" +#include "core/volumemanagerdevice_p.h" /** Constructs an abstract Volume Manager Device with an empty PartitionTable. * + * @param name the Device's name + * @param deviceNode the Device's node + * @param logicalExtentSize the logical extent size that device uses */ -VolumeManagerDevice::VolumeManagerDevice(const QString& name, +VolumeManagerDevice::VolumeManagerDevice(std::shared_ptr d, + const QString& name, const QString& deviceNode, - const qint64 logicalSize, + const qint64 logicalExtentSize, const qint64 totalLogical, const QString& iconName, Device::Type type) - : Device(name, deviceNode, logicalSize, totalLogical, iconName, type) + : Device(std::static_pointer_cast(d), name, deviceNode, logicalExtentSize, totalLogical, iconName, type) { } diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index be59eb5..60dd4d3 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -26,6 +26,8 @@ #include #include +class VolumeManagerDevicePrivate; + /** A Volume Manager of physical devices represented as an abstract device. * * VolumeManagerDevice is an abstract device class for volume manager. e.g: LVM, SoftRAID. @@ -40,8 +42,7 @@ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device Q_DISABLE_COPY(VolumeManagerDevice) public: - - VolumeManagerDevice(const QString& name, const QString& deviceNode, const qint64 logicalSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device); + VolumeManagerDevice(std::shared_ptr d, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device); /** * @return list of physical device's path that makes up volumeManagerDevice.(e.g: /dev/sda, /dev/sdb1) diff --git a/src/core/volumemanagerdevice_p.h b/src/core/volumemanagerdevice_p.h new file mode 100644 index 0000000..6061c26 --- /dev/null +++ b/src/core/volumemanagerdevice_p.h @@ -0,0 +1,27 @@ +/************************************************************************* + * Copyright (C) 2018 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#ifndef KPMCORE_VOLUMEMANAGERDEVICE_P_H +#define KPMCORE_VOLUMEMANAGERDEVICE_P_H + +#include "core/device_p.h" + +class VolumeManagerDevicePrivate : public DevicePrivate +{ +}; + +#endif From 1021e375b4eef13f20487b303181c669b78d5e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 02:45:24 +0100 Subject: [PATCH 082/175] Create a new d-pointer when copying Device class. Fixes a crash in Calamares --- src/core/device.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/device.cpp b/src/core/device.cpp index d6f576c..cc1d29d 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -55,6 +55,7 @@ Device::Device(std::shared_ptr d_ptr, Device::Device(const Device& other) : QObject() { + d = std::make_shared(); d->m_Name = other.d->m_Name; d->m_DeviceNode = other.d->m_DeviceNode; d->m_LogicalSectorSize = other.d->m_LogicalSectorSize; From 3ccd04e675cdda72c5f15aae2a948e58b251049a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 02:57:45 +0100 Subject: [PATCH 083/175] Switch Device::Type enum to enum class. --- src/core/device.cpp | 2 +- src/core/device.h | 12 ++++++------ src/core/diskdevice.cpp | 2 +- src/core/lvmdevice.cpp | 2 +- src/core/operationstack.cpp | 2 +- src/core/partitiontable.cpp | 12 ++++++------ src/core/volumemanagerdevice.h | 2 +- src/jobs/createfilesystemjob.cpp | 4 ++-- src/jobs/createpartitionjob.cpp | 4 ++-- src/jobs/createpartitiontablejob.cpp | 4 ++-- src/jobs/deactivatelogicalvolumejob.cpp | 2 +- src/jobs/deactivatevolumegroupjob.cpp | 2 +- src/jobs/deletefilesystemjob.cpp | 2 +- src/jobs/deletepartitionjob.cpp | 4 ++-- src/jobs/removevolumegroupjob.cpp | 2 +- src/jobs/setpartgeometryjob.cpp | 4 ++-- src/ops/createpartitiontableoperation.cpp | 2 +- src/ops/deactivatevolumegroupoperation.cpp | 2 +- src/ops/removevolumegroupoperation.cpp | 2 +- 19 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/core/device.cpp b/src/core/device.cpp index cc1d29d..fce2f05 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -45,7 +45,7 @@ Device::Device(std::shared_ptr d_ptr, d->m_TotalLogical = totalLogicalSectors; d->m_PartitionTable = nullptr; d->m_IconName = iconName.isEmpty() ? QStringLiteral("drive-harddisk") : iconName; - d->m_SmartStatus = type == Device::Disk_Device ? std::make_shared(deviceNode) : nullptr; + d->m_SmartStatus = type == Device::Type::Disk_Device ? std::make_shared(deviceNode) : nullptr; d->m_Type = type; } diff --git a/src/core/device.h b/src/core/device.h index f99e642..5425539 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -50,15 +50,15 @@ class LIBKPMCORE_EXPORT Device : public QObject friend class CoreBackend; public: - enum Type { - Disk_Device = 0, - LVM_Device = 1, /* VG */ - RAID_Device = 2, /* software RAID device */ - Unknown_Device = 4 + enum class Type { + Unknown_Device, + Disk_Device, + LVM_Device, /* VG */ + RAID_Device, /* software RAID device */ }; protected: - explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Disk_Device); + explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Type::Disk_Device); public: explicit Device(const Device& other); diff --git a/src/core/diskdevice.cpp b/src/core/diskdevice.cpp index c23cb58..38c8175 100644 --- a/src/core/diskdevice.cpp +++ b/src/core/diskdevice.cpp @@ -99,7 +99,7 @@ DiskDevice::DiskDevice(const QString& name, qint32 cylinders, qint64 sectorSize, const QString& iconName) - : Device(std::make_shared(), name, deviceNode, sectorSize, (static_cast(heads) * cylinders * numSectors), iconName, Device::Disk_Device) + : Device(std::make_shared(), name, deviceNode, sectorSize, (static_cast(heads) * cylinders * numSectors), iconName, Device::Type::Disk_Device) { d_ptr->m_Heads = heads; d_ptr->m_SectorsPerTrack = numSectors; diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 917410c..118cd4f 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -63,7 +63,7 @@ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName) getPeSize(vgName), getTotalPE(vgName), iconName, - Device::LVM_Device) + Device::Type::LVM_Device) { d_ptr->m_peSize = logicalSize(); d_ptr->m_totalPE = totalLogical(); diff --git a/src/core/operationstack.cpp b/src/core/operationstack.cpp index 8e7bd57..0a9b9f5 100644 --- a/src/core/operationstack.cpp +++ b/src/core/operationstack.cpp @@ -555,7 +555,7 @@ void OperationStack::addDevice(Device* d) static bool deviceLessThan(const Device* d1, const Device* d2) { // Display alphabetically sorted disk devices above LVM VGs - if (d1->type() == Device::LVM_Device && d2->type() == Device::Disk_Device ) + if (d1->type() == Device::Type::LVM_Device && d2->type() == Device::Type::Disk_Device ) return false; return d1->deviceNode() <= d2->deviceNode(); diff --git a/src/core/partitiontable.cpp b/src/core/partitiontable.cpp index aca5149..acc2080 100644 --- a/src/core/partitiontable.cpp +++ b/src/core/partitiontable.cpp @@ -274,7 +274,7 @@ QStringList PartitionTable::flagNames(Flags flags) bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent, qint64& start, qint64& end) { - if (d.type() == Device::Disk_Device) { + if (d.type() == Device::Type::Disk_Device) { const DiskDevice& device = dynamic_cast(d); if (!parent.isRoot()) { Partition* extended = dynamic_cast(&parent); @@ -295,7 +295,7 @@ bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent, } return end - start + 1 >= PartitionAlignment::sectorAlignment(device); - } else if (d.type() == Device::LVM_Device) { + } else if (d.type() == Device::Type::LVM_Device) { if (end - start + 1 > 0) { return true; } @@ -319,7 +319,7 @@ Partition* createUnallocated(const Device& device, PartitionNode& parent, qint64 r |= PartitionRole::Logical; // Mark unallocated space in LVM VG as LVM LV so that pasting can be easily disabled (it does not work yet) - if (device.type() == Device::LVM_Device) + if (device.type() == Device::Type::LVM_Device) r |= PartitionRole::Lvm_Lv; if (!PartitionTable::getUnallocatedRange(device, parent, start, end)) @@ -379,7 +379,7 @@ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64 qint64 lastEnd = start; - if (d.type() == Device::LVM_Device && !p->children().isEmpty()) { + if (d.type() == Device::Type::LVM_Device && !p->children().isEmpty()) { // rearranging the sectors of all partitions to keep unallocated space at the end lastEnd = 0; std::sort(children().begin(), children().end(), [](const Partition* p1, const Partition* p2) { return p1->deviceNode() < p2->deviceNode(); }); @@ -428,7 +428,7 @@ void PartitionTable::updateUnallocated(const Device& d) qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t) { Q_UNUSED(t) - if (d.type() == Device::LVM_Device) { + if (d.type() == Device::Type::LVM_Device) { return 0; } @@ -518,7 +518,7 @@ bool PartitionTable::tableTypeIsReadOnly(TableType l) */ bool PartitionTable::isSectorBased(const Device& d) const { - if (d.type() == Device::Disk_Device) { + if (d.type() == Device::Type::Disk_Device) { const DiskDevice& diskDevice = dynamic_cast(d); if (type() == PartitionTable::msdos) { diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index 60dd4d3..891aa68 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -42,7 +42,7 @@ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device Q_DISABLE_COPY(VolumeManagerDevice) public: - VolumeManagerDevice(std::shared_ptr d, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Unknown_Device); + VolumeManagerDevice(std::shared_ptr d, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogical, const QString& iconName = QString(), Device::Type type = Device::Type::Unknown_Device); /** * @return list of physical device's path that makes up volumeManagerDevice.(e.g: /dev/sda, /dev/sdb1) diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index c4894e3..264f219 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -59,7 +59,7 @@ bool CreateFileSystemJob::run(Report& parent) else createResult = partition().fileSystem().create(*report, partition().deviceNode()); if (createResult) { - if (device().type() == Device::Disk_Device) { + if (device().type() == Device::Type::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { @@ -75,7 +75,7 @@ bool CreateFileSystemJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); } else report->line() << xi18nc("@info:progress", "Could not open device %1 to set the system type for partition %2.", device().deviceNode(), partition().deviceNode()); - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { rval = true; } } diff --git a/src/jobs/createpartitionjob.cpp b/src/jobs/createpartitionjob.cpp index a67a132..79f635e 100644 --- a/src/jobs/createpartitionjob.cpp +++ b/src/jobs/createpartitionjob.cpp @@ -50,7 +50,7 @@ bool CreatePartitionJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Disk_Device) { + if (device().type() == Device::Type::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { @@ -70,7 +70,7 @@ bool CreatePartitionJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to create new partition %2.", device().deviceNode(), partition().deviceNode()); } else report->line() << xi18nc("@info:progress", "Could not open device %1 to create new partition %2.", device().deviceNode(), partition().deviceNode()); - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { LvmDevice& dev = dynamic_cast(device()); partition().setState(Partition::StateNone); diff --git a/src/jobs/createpartitiontablejob.cpp b/src/jobs/createpartitiontablejob.cpp index 8ceb8b9..557a5e4 100644 --- a/src/jobs/createpartitiontablejob.cpp +++ b/src/jobs/createpartitiontablejob.cpp @@ -44,7 +44,7 @@ bool CreatePartitionTableJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Disk_Device) { + if (device().type() == Device::Type::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice != nullptr) { @@ -53,7 +53,7 @@ bool CreatePartitionTableJob::run(Report& parent) rval = backendDevice->createPartitionTable(*report, *device().partitionTable()); } else report->line() << xi18nc("@info:progress", "Creating partition table failed: Could not open device %1.", device().deviceNode()); - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { //TODO: figure what to do with LVM partitionTable } diff --git a/src/jobs/deactivatelogicalvolumejob.cpp b/src/jobs/deactivatelogicalvolumejob.cpp index 327ad5c..5ce85da 100644 --- a/src/jobs/deactivatelogicalvolumejob.cpp +++ b/src/jobs/deactivatelogicalvolumejob.cpp @@ -41,7 +41,7 @@ bool DeactivateLogicalVolumeJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::LVM_Device) { + if (device().type() == Device::Type::LVM_Device) { for (const auto &p : device().partitionTable()->children()) { if (!p->roles().has(PartitionRole::Unallocated)) { if (!LvmDevice::deactivateLV(*report, *p)) { diff --git a/src/jobs/deactivatevolumegroupjob.cpp b/src/jobs/deactivatevolumegroupjob.cpp index ae56ac6..2cc2ea3 100644 --- a/src/jobs/deactivatevolumegroupjob.cpp +++ b/src/jobs/deactivatevolumegroupjob.cpp @@ -39,7 +39,7 @@ bool DeactivateVolumeGroupJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::LVM_Device) { + if (device().type() == Device::Type::LVM_Device) { rval = LvmDevice::deactivateVG(*report, static_cast(device())); } const auto lvmPVs = static_cast(device()).physicalVolumes(); diff --git a/src/jobs/deletefilesystemjob.cpp b/src/jobs/deletefilesystemjob.cpp index 6ff797e..176f851 100644 --- a/src/jobs/deletefilesystemjob.cpp +++ b/src/jobs/deletefilesystemjob.cpp @@ -65,7 +65,7 @@ bool DeleteFileSystemJob::run(Report& parent) if (partition().roles().has(PartitionRole::Extended)) { rval = true; - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { rval = true; } else { diff --git a/src/jobs/deletepartitionjob.cpp b/src/jobs/deletepartitionjob.cpp index 20bada2..07c30ff 100644 --- a/src/jobs/deletepartitionjob.cpp +++ b/src/jobs/deletepartitionjob.cpp @@ -57,7 +57,7 @@ bool DeletePartitionJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Disk_Device) { + if (device().type() == Device::Type::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { @@ -74,7 +74,7 @@ bool DeletePartitionJob::run(Report& parent) report->line() << xi18nc("@info:progress", "Could not open partition table on device %1 to delete partition %2.", device().deviceNode(), partition().deviceNode()); } else report->line() << xi18nc("@info:progress", "Deleting partition failed: Could not open device %1.", device().deviceNode()); - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { LvmDevice& dev = dynamic_cast(device()); rval = LvmDevice::removeLV(*report, dev, partition()); } diff --git a/src/jobs/removevolumegroupjob.cpp b/src/jobs/removevolumegroupjob.cpp index d5026ae..97792f7 100644 --- a/src/jobs/removevolumegroupjob.cpp +++ b/src/jobs/removevolumegroupjob.cpp @@ -37,7 +37,7 @@ bool RemoveVolumeGroupJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::LVM_Device) { + if (device().type() == Device::Type::LVM_Device) { rval = LvmDevice::removeVG(*report, dynamic_cast(device())); } diff --git a/src/jobs/setpartgeometryjob.cpp b/src/jobs/setpartgeometryjob.cpp index 153c352..30e218a 100644 --- a/src/jobs/setpartgeometryjob.cpp +++ b/src/jobs/setpartgeometryjob.cpp @@ -55,7 +55,7 @@ bool SetPartGeometryJob::run(Report& parent) Report* report = jobStarted(parent); - if(device().type() == Device::Disk_Device) { + if(device().type() == Device::Type::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { @@ -72,7 +72,7 @@ bool SetPartGeometryJob::run(Report& parent) } } else report->line() << xi18nc("@info:progress", "Could not open device %1 while trying to resize/move partition %2.", device().deviceNode(), partition().deviceNode()); - } else if (device().type() == Device::LVM_Device) { + } else if (device().type() == Device::Type::LVM_Device) { partition().setFirstSector(newStart()); partition().setLastSector(newStart() + newLength() - 1); diff --git a/src/ops/createpartitiontableoperation.cpp b/src/ops/createpartitiontableoperation.cpp index 9260be6..f3ed270 100644 --- a/src/ops/createpartitiontableoperation.cpp +++ b/src/ops/createpartitiontableoperation.cpp @@ -93,7 +93,7 @@ bool CreatePartitionTableOperation::execute(Report& parent) */ bool CreatePartitionTableOperation::canCreate(const Device* device) { - return (device != nullptr) && (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted()) && (device->type() != Device::LVM_Device); + return (device != nullptr) && (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted()) && (device->type() != Device::Type::LVM_Device); } QString CreatePartitionTableOperation::description() const diff --git a/src/ops/deactivatevolumegroupoperation.cpp b/src/ops/deactivatevolumegroupoperation.cpp index a002e84..2a2db83 100644 --- a/src/ops/deactivatevolumegroupoperation.cpp +++ b/src/ops/deactivatevolumegroupoperation.cpp @@ -63,7 +63,7 @@ void DeactivateVolumeGroupOperation::undo() */ bool DeactivateVolumeGroupOperation::isDeactivatable(const VolumeManagerDevice* dev) { - if (dev->type() == Device::LVM_Device) { + if (dev->type() == Device::Type::LVM_Device) { for (const auto &p : dev->partitionTable()->children()) { if (p->isMounted()) { return false; diff --git a/src/ops/removevolumegroupoperation.cpp b/src/ops/removevolumegroupoperation.cpp index b523c83..605de3b 100644 --- a/src/ops/removevolumegroupoperation.cpp +++ b/src/ops/removevolumegroupoperation.cpp @@ -61,7 +61,7 @@ void RemoveVolumeGroupOperation::undo() bool RemoveVolumeGroupOperation::isRemovable(const VolumeManagerDevice* dev) { // TODO: allow removal when LVs are inactive. - if (dev->type() == Device::LVM_Device) { + if (dev->type() == Device::Type::LVM_Device) { if (dev->partitionTable()->children().count() == 0) // This is necessary to prevent a crash during applying of operations return true; else if (dev->partitionTable()->children().count() > 1) From 844f7b3d591986c2c246893720b3081c2040665b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 03:14:30 +0100 Subject: [PATCH 084/175] LvmDevice: switch away from manual pointers. --- src/core/lvmdevice.cpp | 21 +++++++-------------- src/core/lvmdevice.h | 5 ++--- src/core/volumemanagerdevice.h | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 118cd4f..b9746e3 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -46,9 +46,9 @@ public: qint64 m_freePE; QString m_UUID; - mutable QStringList* m_LVPathList; + mutable QStringList m_LVPathList; QVector m_PVs; - mutable QHash* m_LVSizeMap; + mutable std::unique_ptr> m_LVSizeMap; }; /** Constructs a representation of LVM device with initialized LV as Partitions @@ -70,8 +70,8 @@ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName) d_ptr->m_freePE = getFreePE(vgName); d_ptr->m_allocPE = d_ptr->m_totalPE - d_ptr->m_freePE; d_ptr->m_UUID = getUUID(vgName); - d_ptr->m_LVPathList = new QStringList(getLVs(vgName)); - d_ptr->m_LVSizeMap = new QHash(); + d_ptr->m_LVPathList = getLVs(vgName); + d_ptr->m_LVSizeMap = std::make_unique>(); initPartitions(); } @@ -84,8 +84,6 @@ QVector LvmDevice::s_DirtyPVs; LvmDevice::~LvmDevice() { - delete d_ptr->m_LVPathList; - delete d_ptr->m_LVSizeMap; } void LvmDevice::initPartitions() @@ -243,9 +241,9 @@ const QStringList LvmDevice::deviceNodes() const return pvList; } -const QStringList LvmDevice::partitionNodes() const +const QStringList& LvmDevice::partitionNodes() const { - return *LVPathList(); + return d_ptr->m_LVPathList; } qint64 LvmDevice::partitionSize(QString& partitionPath) const @@ -536,11 +534,6 @@ QString LvmDevice::UUID() const return d_ptr->m_UUID; } -QStringList* LvmDevice::LVPathList() const -{ - return d_ptr->m_LVPathList; -} - QVector & LvmDevice::physicalVolumes() { return d_ptr->m_PVs; @@ -551,7 +544,7 @@ const QVector & LvmDevice::physicalVolumes() const return d_ptr->m_PVs; } -QHash* LvmDevice::LVSizeMap() const +std::unique_ptr>& LvmDevice::LVSizeMap() const { return d_ptr->m_LVSizeMap; } diff --git a/src/core/lvmdevice.h b/src/core/lvmdevice.h index 08b768e..f4413d8 100644 --- a/src/core/lvmdevice.h +++ b/src/core/lvmdevice.h @@ -51,7 +51,7 @@ public: public: const QStringList deviceNodes() const override; - const QStringList partitionNodes() const override; + const QStringList& partitionNodes() const override; qint64 partitionSize(QString& partitionPath) const override; static QVector s_DirtyPVs; @@ -98,12 +98,11 @@ public: qint64 allocatedPE() const; qint64 freePE() const; QString UUID() const; - QStringList* LVPathList() const; QVector & physicalVolumes(); const QVector & physicalVolumes() const; protected: - QHash* LVSizeMap() const; + std::unique_ptr>& LVSizeMap() const; }; #endif diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index 891aa68..f1750dd 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -52,7 +52,7 @@ public: /** * @return list of logical partition's path. */ - virtual const QStringList partitionNodes() const = 0; + virtual const QStringList& partitionNodes() const = 0; /** * @return size of logical partition at the given path in bytes. From 87f0d9d0a758e1dc1b997e3cd9cfdc5fa9d9298d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 03:18:12 +0100 Subject: [PATCH 085/175] micro-optimization: QStringLiteral->QLatin1Char --- src/core/lvmdevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index b9746e3..cab4a9e 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -256,7 +256,7 @@ const QStringList LvmDevice::getVGs() QStringList vgList; QString output = getField(QStringLiteral("vg_name")); if (!output.isEmpty()) { - const QStringList vgNameList = output.split(QStringLiteral("\n"), QString::SkipEmptyParts); + const QStringList vgNameList = output.split(QLatin1Char('\n'), QString::SkipEmptyParts); for (const auto &vgName : vgNameList) { vgList.append(vgName.trimmed()); } @@ -270,7 +270,7 @@ const QStringList LvmDevice::getLVs(const QString& vgName) QString cmdOutput = getField(QStringLiteral("lv_path"), vgName); if (cmdOutput.size()) { - const QStringList tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts); + const QStringList tempPathList = cmdOutput.split(QLatin1Char('\n'), QString::SkipEmptyParts); for (const auto &lvPath : tempPathList) { lvPathList.append(lvPath.trimmed()); } From 622def3b567d37f0699f627c51d5a3fe27672815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 15:14:34 +0100 Subject: [PATCH 086/175] Convert more enums to scoped enums. --- src/core/fstab.cpp | 24 ++++---- src/core/fstab.h | 6 +- src/core/partitionalignment.cpp | 4 +- src/core/smartattribute.cpp | 24 ++++---- src/core/smartattribute.h | 6 +- src/core/smartdiskinformation.cpp | 15 +++-- src/core/smartdiskinformation.h | 19 +++--- src/core/smartstatus.cpp | 80 +++++++++++++------------- src/core/smartstatus.h | 4 +- src/fs/btrfs.cpp | 4 +- src/fs/exfat.cpp | 2 +- src/fs/ext2.cpp | 2 +- src/fs/ext3.cpp | 2 +- src/fs/ext4.cpp | 2 +- src/fs/f2fs.cpp | 4 +- src/fs/fat12.cpp | 4 +- src/fs/fat16.cpp | 4 +- src/fs/fat32.cpp | 4 +- src/fs/filesystem.cpp | 4 +- src/fs/hfs.cpp | 2 +- src/fs/hfsplus.cpp | 2 +- src/fs/hpfs.cpp | 2 +- src/fs/jfs.cpp | 4 +- src/fs/luks.h | 7 +-- src/fs/luks2.cpp | 10 ++-- src/fs/lvm2_pv.cpp | 2 +- src/fs/nilfs2.cpp | 4 +- src/fs/ntfs.cpp | 4 +- src/fs/ocfs2.cpp | 4 +- src/fs/reiser4.cpp | 2 +- src/fs/reiserfs.cpp | 4 +- src/fs/xfs.cpp | 4 +- src/fs/zfs.cpp | 4 +- src/jobs/resizefilesystemjob.cpp | 2 +- src/jobs/resizevolumegroupjob.cpp | 8 +-- src/jobs/resizevolumegroupjob.h | 6 +- src/ops/deleteoperation.cpp | 8 +-- src/ops/deleteoperation.h | 8 +-- src/ops/resizevolumegroupoperation.cpp | 4 +- src/plugins/sfdisk/sfdiskbackend.cpp | 2 +- src/util/capacity.cpp | 18 +++--- src/util/capacity.h | 6 +- src/util/globallog.h | 12 ++-- test/testsmart.cpp | 2 +- 44 files changed, 171 insertions(+), 174 deletions(-) diff --git a/src/core/fstab.cpp b/src/core/fstab.cpp index 4cf9ee4..6bdc7f2 100644 --- a/src/core/fstab.cpp +++ b/src/core/fstab.cpp @@ -31,7 +31,7 @@ #include #include -static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode); +static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType, QString& m_deviceNode); static QString findBlkIdDevice(const char *token, const QString& value); struct FstabEntryPrivate @@ -44,7 +44,7 @@ struct FstabEntryPrivate int m_dumpFreq; int m_passNumber; QString m_comment; - FstabEntryType m_entryType; + FstabEntry::Type m_entryType; }; FstabEntry::FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq, int passNumber, const QString& comment) : @@ -103,7 +103,7 @@ FstabEntryList readFstabEntries( const QString& fstabPath ) } fstabFile.close(); - if (fstabEntries.back().entryType() == comment && fstabEntries.back().comment().isEmpty()) + if (fstabEntries.back().entryType() == FstabEntry::Type::comment && fstabEntries.back().comment().isEmpty()) fstabEntries.pop_back(); } @@ -156,7 +156,7 @@ const QString& FstabEntry::comment() const return d->m_comment; } -FstabEntryType FstabEntry::entryType() const +FstabEntry::Type FstabEntry::entryType() const { return d->m_entryType; } @@ -207,23 +207,23 @@ static QString findBlkIdDevice(const char *token, const QString& value) return rval; } -static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QString& m_deviceNode) +static void parseFsSpec(const QString& m_fsSpec, FstabEntry::Type& m_entryType, QString& m_deviceNode) { - m_entryType = FstabEntryType::comment; + m_entryType = FstabEntry::Type::comment; if (m_fsSpec.startsWith(QStringLiteral("UUID="))) { - m_entryType = FstabEntryType::uuid; + m_entryType = FstabEntry::Type::uuid; m_deviceNode = findBlkIdDevice("UUID", QString(m_fsSpec).remove(QStringLiteral("UUID="))); } else if (m_fsSpec.startsWith(QStringLiteral("LABEL="))) { - m_entryType = FstabEntryType::label; + m_entryType = FstabEntry::Type::label; m_deviceNode = findBlkIdDevice("LABEL", QString(m_fsSpec).remove(QStringLiteral("LABEL="))); } else if (m_fsSpec.startsWith(QStringLiteral("PARTUUID="))) { - m_entryType = FstabEntryType::uuid; + m_entryType = FstabEntry::Type::uuid; m_deviceNode = findBlkIdDevice("PARTUUID", QString(m_fsSpec).remove(QStringLiteral("PARTUUID="))); } else if (m_fsSpec.startsWith(QStringLiteral("PARTLABEL="))) { - m_entryType = FstabEntryType::label; + m_entryType = FstabEntry::Type::label; m_deviceNode = findBlkIdDevice("PARTLABEL", QString(m_fsSpec).remove(QStringLiteral("PARTLABEL="))); } else if (m_fsSpec.startsWith(QStringLiteral("/"))) { - m_entryType = FstabEntryType::deviceNode; + m_entryType = FstabEntry::Type::deviceNode; m_deviceNode = m_fsSpec; } } @@ -231,7 +231,7 @@ static void parseFsSpec(const QString& m_fsSpec, FstabEntryType& m_entryType, QS static void writeEntry(QFile& output, const FstabEntry& entry) { QTextStream s(&output); - if (entry.entryType() == FstabEntryType::comment) { + if (entry.entryType() == FstabEntry::Type::comment) { s << entry.comment() << "\n"; return; } diff --git a/src/core/fstab.h b/src/core/fstab.h index ca3c8b6..d158813 100644 --- a/src/core/fstab.h +++ b/src/core/fstab.h @@ -27,8 +27,6 @@ struct FstabEntryPrivate; -enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment }; - /** Base class for fstab handling. FstabEntry stores a single line of /etc/fstab file which can be a comment @@ -39,6 +37,8 @@ enum FstabEntryType { deviceNode, uuid, label, partlabel, partuuid, comment }; class LIBKPMCORE_EXPORT FstabEntry { public: + enum class Type { deviceNode, uuid, label, partlabel, partuuid, comment }; + FstabEntry(const QString& fsSpec, const QString& mountPoint, const QString& type, const QString& options, int dumpFreq = 0, int passNumber = 0, const QString& comment = QString()); /** @@ -84,7 +84,7 @@ public: /** * @return the type of fstab entry, e.g. device node or UUID or comment only */ - FstabEntryType entryType() const; + Type entryType() const; /** * @param s the new value for the fs_spec field of fstab entry diff --git a/src/core/partitionalignment.cpp b/src/core/partitionalignment.cpp index e38c569..d32da6d 100644 --- a/src/core/partitionalignment.cpp +++ b/src/core/partitionalignment.cpp @@ -85,10 +85,10 @@ bool PartitionAlignment::isAligned(const Device& d, const Partition& p, bool qui bool PartitionAlignment::isAligned(const Device& d, const Partition& p, qint64 newFirst, qint64 newLast, bool quiet) { if (firstDelta(d, p, newFirst) && !quiet) - Log(Log::warning) << xi18nc("@info:status", "Partition %1 is not properly aligned (first sector: %2, modulo: %3).", p.deviceNode(), newFirst, firstDelta(d, p, newFirst)); + Log(Log::Level::warning) << xi18nc("@info:status", "Partition %1 is not properly aligned (first sector: %2, modulo: %3).", p.deviceNode(), newFirst, firstDelta(d, p, newFirst)); if (lastDelta(d, p, newLast) && !quiet) - Log(Log::warning) << xi18nc("@info:status", "Partition %1 is not properly aligned (last sector: %2, modulo: %3).", p.deviceNode(), newLast, lastDelta(d, p, newLast)); + Log(Log::Level::warning) << xi18nc("@info:status", "Partition %1 is not properly aligned (last sector: %2, modulo: %3).", p.deviceNode(), newLast, lastDelta(d, p, newLast)); return firstDelta(d, p, newFirst) == 0 && lastDelta(d, p, newLast) == 0; } diff --git a/src/core/smartattribute.cpp b/src/core/smartattribute.cpp index 6e29056..f27bb07 100644 --- a/src/core/smartattribute.cpp +++ b/src/core/smartattribute.cpp @@ -35,8 +35,8 @@ SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) : m_Id(a.id()), m_Name(getAttrName(a.id())), m_Desc(getAttrDescription(a.id())), - m_FailureType(a.prefailure() ? PreFailure : OldAge), - m_UpdateType(a.online() ? Online : Offline), + m_FailureType(a.prefailure() ? FailureType::PreFailure : FailureType::OldAge), + m_UpdateType(a.online() ? UpdateType::Online : UpdateType::Offline), m_Current(a.currentValueValid() ? a.currentValue() : -1), m_Worst(a.worstValueValid() ? a.worstValue() : -1), m_Threshold(a.thresholdValid() ? a.threshold() : -1), @@ -50,19 +50,19 @@ SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) : QString SmartAttribute::assessmentToString(Assessment a) { switch (a) { - case Failing: + case Assessment::Failing: return xi18nc("@item:intable", "failing"); - case HasFailed: + case Assessment::HasFailed: return xi18nc("@item:intable", "has failed"); - case Warning: + case Assessment::Warning: return xi18nc("@item:intable", "warning"); - case Good: + case Assessment::Good: return xi18nc("@item:intable", "good"); - case NotApplicable: + case Assessment::NotApplicable: default: return xi18nc("@item:intable not applicable", "N/A"); } @@ -216,7 +216,7 @@ static QString getAttrDescription(qint32 id) static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a) { - SmartAttribute::Assessment rval = SmartAttribute::NotApplicable; + SmartAttribute::Assessment rval = SmartAttribute::Assessment::NotApplicable; bool failed = false; bool hasFailed = false; @@ -235,13 +235,13 @@ static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& } if (failed) - rval = SmartAttribute::Failing; + rval = SmartAttribute::Assessment::Failing; else if (hasFailed) - rval = SmartAttribute::HasFailed; + rval = SmartAttribute::Assessment::HasFailed; else if (a.warn()) - rval = SmartAttribute::Warning; + rval = SmartAttribute::Assessment::Warning; else if (a.goodNowValid()) - rval = SmartAttribute::Good; + rval = SmartAttribute::Assessment::Good; return rval; } diff --git a/src/core/smartattribute.h b/src/core/smartattribute.h index 08687d1..2df9ae9 100644 --- a/src/core/smartattribute.h +++ b/src/core/smartattribute.h @@ -27,17 +27,17 @@ class SmartAttributeParsedData; class LIBKPMCORE_EXPORT SmartAttribute { public: - enum FailureType { + enum class FailureType { PreFailure, OldAge }; - enum UpdateType { + enum class UpdateType { Online, Offline }; - enum Assessment { + enum class Assessment { NotApplicable, Failing, HasFailed, diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index fc46d21..cc18c7c 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -34,7 +34,7 @@ SmartDiskInformation::SmartDiskInformation() : m_BadAttributeNow(false), m_BadAttributeInThePast(false), m_SelfTestExecutionStatus(SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER), - m_Overall(SmartDiskInformation::SMART_OVERALL_BAD_STATUS) + m_Overall(SmartDiskInformation::Overall::BadStatus) { } @@ -62,36 +62,35 @@ void SmartDiskInformation::updateBadSectors() void SmartDiskInformation::updateOverall() { if (!smartStatus()) { - m_Overall = SMART_OVERALL_BAD_STATUS; + m_Overall = Overall::BadStatus; return; } quint64 sector_threshold = u64log2(size() / 512) * 1024; if (badSectors() >= sector_threshold) { - m_Overall = SMART_OVERALL_BAD_SECTOR_MANY; + m_Overall = Overall::BadSectorsMany; return; } validateBadAttributes(); if (m_BadAttributeNow) { - m_Overall = SMART_OVERALL_BAD_ATTRIBUTE_NOW; + m_Overall = Overall::BadAttributeNow; return; } if (badSectors() > 0) { - m_Overall = SMART_OVERALL_BAD_SECTOR; + m_Overall = Overall::BadSector; return; } if (m_BadAttributeInThePast) { - m_Overall = SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST; + m_Overall = Overall::BadAttributeInThePast; return; } - m_Overall = SMART_OVERALL_GOOD; - + m_Overall = Overall::Good; } /** Update the temperature value based on SMART attributes diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index 996c2fc..4c55f41 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -48,14 +48,13 @@ public: }; /** SMART overall state */ - enum SmartOverall { - SMART_OVERALL_GOOD, - SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST, - SMART_OVERALL_BAD_SECTOR, - SMART_OVERALL_BAD_ATTRIBUTE_NOW, - SMART_OVERALL_BAD_SECTOR_MANY, - SMART_OVERALL_BAD_STATUS, - _SMART_OVERALL_MAX + enum class Overall { + Good, + BadAttributeInThePast, + BadSector, + BadAttributeNow, + BadSectorsMany, + BadStatus, }; public: @@ -105,7 +104,7 @@ public: return m_SelfTestExecutionStatus; /**< @return SMART self execution status */ } - SmartOverall overall() const + Overall overall() const { return m_Overall; /**< @return SMART overall status */ } @@ -192,7 +191,7 @@ private: bool m_BadAttributeNow; bool m_BadAttributeInThePast; SmartSelfTestExecutionStatus m_SelfTestExecutionStatus; - SmartOverall m_Overall; + Overall m_Overall; QList m_Attributes; }; diff --git a/src/core/smartstatus.cpp b/src/core/smartstatus.cpp index 3c8a35a..855d99a 100644 --- a/src/core/smartstatus.cpp +++ b/src/core/smartstatus.cpp @@ -37,8 +37,8 @@ SmartStatus::SmartStatus(const QString &device_path) : m_ModelName(), m_Serial(), m_Firmware(), - m_Overall(Bad), - m_SelfTestStatus(Success), + m_Overall(Overall::Bad), + m_SelfTestStatus(SelfTestStatus::Success), m_Temp(0), m_BadSectors(0), m_PowerCycles(0), @@ -73,72 +73,72 @@ void SmartStatus::update() switch (disk->selfTestExecutionStatus()) { case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ABORTED: - setSelfTestStatus(Aborted); + setSelfTestStatus(SelfTestStatus::Aborted); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED: - setSelfTestStatus(Interrupted); + setSelfTestStatus(SelfTestStatus::Interrupted); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_FATAL: - setSelfTestStatus(Fatal); + setSelfTestStatus(SelfTestStatus::Fatal); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN: - setSelfTestStatus(ErrorUnknown); + setSelfTestStatus(SelfTestStatus::ErrorUnknown); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL: - setSelfTestStatus(ErrorEletrical); + setSelfTestStatus(SelfTestStatus::ErrorEletrical); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO: - setSelfTestStatus(ErrorServo); + setSelfTestStatus(SelfTestStatus::ErrorServo); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ: - setSelfTestStatus(ErrorRead); + setSelfTestStatus(SelfTestStatus::ErrorRead); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING: - setSelfTestStatus(ErrorHandling); + setSelfTestStatus(SelfTestStatus::ErrorHandling); break; case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS: - setSelfTestStatus(InProgress); + setSelfTestStatus(SelfTestStatus::InProgress); break; default: case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER: - setSelfTestStatus(Success); + setSelfTestStatus(SelfTestStatus::Success); break; } switch (disk->overall()) { - case SmartDiskInformation::SMART_OVERALL_GOOD: - setOverall(Good); + case SmartDiskInformation::Overall::Good: + setOverall(Overall::Good); break; - case SmartDiskInformation::SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST: - setOverall(BadPast); + case SmartDiskInformation::Overall::BadAttributeInThePast: + setOverall(Overall::BadPast); break; - case SmartDiskInformation::SMART_OVERALL_BAD_SECTOR: - setOverall(BadSectors); + case SmartDiskInformation::Overall::BadSector: + setOverall(Overall::BadSectors); break; - case SmartDiskInformation::SMART_OVERALL_BAD_ATTRIBUTE_NOW: - setOverall(BadNow); + case SmartDiskInformation::Overall::BadAttributeNow: + setOverall(Overall::BadNow); break; - case SmartDiskInformation::SMART_OVERALL_BAD_SECTOR_MANY: - setOverall(BadSectorsMany); + case SmartDiskInformation::Overall::BadSectorsMany: + setOverall(Overall::BadSectorsMany); break; default: - case SmartDiskInformation::SMART_OVERALL_BAD_STATUS: - setOverall(Bad); + case SmartDiskInformation::Overall::BadStatus: + setOverall(Overall::Bad); break; } @@ -167,34 +167,34 @@ QString SmartStatus::tempToString(quint64 mkelvin) QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s) { switch (s) { - case Aborted: + case SelfTestStatus::Aborted: return xi18nc("@item", "Aborted"); - case Interrupted: + case SelfTestStatus::Interrupted: return xi18nc("@item", "Interrupted"); - case Fatal: + case SelfTestStatus::Fatal: return xi18nc("@item", "Fatal error"); - case ErrorUnknown: + case SelfTestStatus::ErrorUnknown: return xi18nc("@item", "Unknown error"); - case ErrorEletrical: + case SelfTestStatus::ErrorEletrical: return xi18nc("@item", "Electrical error"); - case ErrorServo: + case SelfTestStatus::ErrorServo: return xi18nc("@item", "Servo error"); - case ErrorRead: + case SelfTestStatus::ErrorRead: return xi18nc("@item", "Read error"); - case ErrorHandling: + case SelfTestStatus::ErrorHandling: return xi18nc("@item", "Handling error"); - case InProgress: + case SelfTestStatus::InProgress: return xi18nc("@item", "Self test in progress"); - case Success: + case SelfTestStatus::Success: default: return xi18nc("@item", "Success"); } @@ -204,22 +204,22 @@ QString SmartStatus::selfTestStatusToString(SmartStatus::SelfTestStatus s) QString SmartStatus::overallAssessmentToString(Overall o) { switch (o) { - case Good: + case Overall::Good: return xi18nc("@item", "Healthy"); - case BadPast: + case Overall::BadPast: return xi18nc("@item", "Has been used outside of its design parameters in the past."); - case BadSectors: + case Overall::BadSectors: return xi18nc("@item", "Has some bad sectors."); - case BadNow: + case Overall::BadNow: return xi18nc("@item", "Is being used outside of its design parameters right now."); - case BadSectorsMany: + case Overall::BadSectorsMany: return xi18nc("@item", "Has many bad sectors."); - case Bad: + case Overall::Bad: default: return xi18nc("@item", "Disk failure is imminent. Backup all data!"); } diff --git a/src/core/smartstatus.h b/src/core/smartstatus.h index 88b410d..b54236d 100644 --- a/src/core/smartstatus.h +++ b/src/core/smartstatus.h @@ -31,7 +31,7 @@ struct SkDisk; class LIBKPMCORE_EXPORT SmartStatus { public: - enum Overall { + enum class Overall { Good, BadPast, BadSectors, @@ -40,7 +40,7 @@ public: Bad }; - enum SelfTestStatus { + enum class SelfTestStatus { Success, Aborted, Interrupted, diff --git a/src/fs/btrfs.cpp b/src/fs/btrfs.cpp index 864cf56..c7c1edb 100644 --- a/src/fs/btrfs.cpp +++ b/src/fs/btrfs.cpp @@ -91,12 +91,12 @@ FileSystem::SupportTool btrfs::supportToolName() const qint64 btrfs::minCapacity() const { - return 256 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 256 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 btrfs::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int btrfs::maxLabelLength() const diff --git a/src/fs/exfat.cpp b/src/fs/exfat.cpp index 46753e8..1971a63 100644 --- a/src/fs/exfat.cpp +++ b/src/fs/exfat.cpp @@ -84,7 +84,7 @@ FileSystem::SupportTool exfat::supportToolName() const qint64 exfat::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int exfat::maxLabelLength() const diff --git a/src/fs/ext2.cpp b/src/fs/ext2.cpp index a2e82a4..fce9274 100644 --- a/src/fs/ext2.cpp +++ b/src/fs/ext2.cpp @@ -84,7 +84,7 @@ FileSystem::SupportTool ext2::supportToolName() const qint64 ext2::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } int ext2::maxLabelLength() const diff --git a/src/fs/ext3.cpp b/src/fs/ext3.cpp index a33f236..7fa67c9 100644 --- a/src/fs/ext3.cpp +++ b/src/fs/ext3.cpp @@ -31,7 +31,7 @@ ext3::ext3(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QStr qint64 ext3::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } bool ext3::create(Report& report, const QString& deviceNode) diff --git a/src/fs/ext4.cpp b/src/fs/ext4.cpp index 30d38dc..0fa3811 100644 --- a/src/fs/ext4.cpp +++ b/src/fs/ext4.cpp @@ -31,7 +31,7 @@ ext4::ext4(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QStr qint64 ext4::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } bool ext4::create(Report& report, const QString& deviceNode) diff --git a/src/fs/f2fs.cpp b/src/fs/f2fs.cpp index d112dac..f8c62cb 100644 --- a/src/fs/f2fs.cpp +++ b/src/fs/f2fs.cpp @@ -100,12 +100,12 @@ FileSystem::SupportTool f2fs::supportToolName() const qint64 f2fs::minCapacity() const { - return 30 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 30 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 f2fs::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); } int f2fs::maxLabelLength() const diff --git a/src/fs/fat12.cpp b/src/fs/fat12.cpp index 2bc0d5e..c059899 100644 --- a/src/fs/fat12.cpp +++ b/src/fs/fat12.cpp @@ -87,12 +87,12 @@ FileSystem::SupportTool fat12::supportToolName() const qint64 fat12::minCapacity() const { - return 1 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 1 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 fat12::maxCapacity() const { - return 255 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 255 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } int fat12::maxLabelLength() const diff --git a/src/fs/fat16.cpp b/src/fs/fat16.cpp index 1b6b3fe..2c768b0 100644 --- a/src/fs/fat16.cpp +++ b/src/fs/fat16.cpp @@ -75,12 +75,12 @@ bool fat16::supportToolFound() const qint64 fat16::minCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 fat16::maxCapacity() const { - return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::GiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 4 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::GiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } bool fat16::create(Report& report, const QString& deviceNode) diff --git a/src/fs/fat32.cpp b/src/fs/fat32.cpp index 7f6151e..4dfb2dd 100644 --- a/src/fs/fat32.cpp +++ b/src/fs/fat32.cpp @@ -32,12 +32,12 @@ fat32::fat32(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QS qint64 fat32::minCapacity() const { - return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 fat32::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } bool fat32::create(Report& report, const QString& deviceNode) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index 0919294..df6eb8c 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -376,13 +376,13 @@ bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) con /** @return the minimum capacity valid for this FileSystem in bytes */ qint64 FileSystem::minCapacity() const { - return 8 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 8 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } /** @return the maximum capacity valid for this FileSystem in bytes */ qint64 FileSystem::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } /** @return the maximum label length valid for this FileSystem */ diff --git a/src/fs/hfs.cpp b/src/fs/hfs.cpp index 98a2d15..15677fc 100644 --- a/src/fs/hfs.cpp +++ b/src/fs/hfs.cpp @@ -73,7 +73,7 @@ FileSystem::SupportTool hfs::supportToolName() const qint64 hfs::maxCapacity() const { - return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); + return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); } int hfs::maxLabelLength() const diff --git a/src/fs/hfsplus.cpp b/src/fs/hfsplus.cpp index f417ea0..6d17540 100644 --- a/src/fs/hfsplus.cpp +++ b/src/fs/hfsplus.cpp @@ -73,7 +73,7 @@ FileSystem::SupportTool hfsplus::supportToolName() const qint64 hfsplus::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int hfsplus::maxLabelLength() const diff --git a/src/fs/hpfs.cpp b/src/fs/hpfs.cpp index aa1941e..55c41a1 100644 --- a/src/fs/hpfs.cpp +++ b/src/fs/hpfs.cpp @@ -43,6 +43,6 @@ hpfs::hpfs(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QStr qint64 hpfs::maxCapacity() const { - return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); + return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); } } diff --git a/src/fs/jfs.cpp b/src/fs/jfs.cpp index da260a4..cc43573 100644 --- a/src/fs/jfs.cpp +++ b/src/fs/jfs.cpp @@ -79,12 +79,12 @@ FileSystem::SupportTool jfs::supportToolName() const qint64 jfs::minCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 jfs::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); } int jfs::maxLabelLength() const diff --git a/src/fs/luks.h b/src/fs/luks.h index dfc761f..7dddba1 100644 --- a/src/fs/luks.h +++ b/src/fs/luks.h @@ -17,8 +17,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_LUKS_H) - +#ifndef KPMCORE_LUKS_H #define KPMCORE_LUKS_H #include "util/libpartitionmanagerexport.h" @@ -43,7 +42,7 @@ public: luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Type::Luks); ~luks() override; - enum KeyLocation { + enum class KeyLocation { unknown, dmcrypt, keyring @@ -225,7 +224,7 @@ protected: qint64 m_PayloadSize; QString m_outerUuid; - luks::KeyLocation m_KeyLocation = unknown; + luks::KeyLocation m_KeyLocation = KeyLocation::unknown; }; } diff --git a/src/fs/luks2.cpp b/src/fs/luks2.cpp index af2ae34..107f51c 100644 --- a/src/fs/luks2.cpp +++ b/src/fs/luks2.cpp @@ -94,7 +94,7 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); - if (m_KeyLocation == keyring) { + if (m_KeyLocation == KeyLocation::keyring) { if (m_passphrase.isEmpty()) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); @@ -110,7 +110,7 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) { QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); - if (m_KeyLocation == keyring) { + if (m_KeyLocation == KeyLocation::keyring) { if (m_passphrase.isEmpty()) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); @@ -126,16 +126,16 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) luks::KeyLocation luks2::keyLocation() { - m_KeyLocation = unknown; + m_KeyLocation = KeyLocation::unknown; ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() }); if (statusCmd.run(-1) && statusCmd.exitCode() == 0) { QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)")); QRegularExpressionMatch rem = re.match(statusCmd.output()); if (rem.hasMatch()) { if (rem.captured(1) == QStringLiteral("keyring")) - m_KeyLocation = keyring; + m_KeyLocation = KeyLocation::keyring; else if (rem.captured(1) == QStringLiteral("dm-crypt")) - m_KeyLocation = dmcrypt; + m_KeyLocation = KeyLocation::dmcrypt; } } diff --git a/src/fs/lvm2_pv.cpp b/src/fs/lvm2_pv.cpp index 62791c8..92778e6 100644 --- a/src/fs/lvm2_pv.cpp +++ b/src/fs/lvm2_pv.cpp @@ -99,7 +99,7 @@ FileSystem::SupportTool lvm2_pv::supportToolName() const qint64 lvm2_pv::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } qint64 lvm2_pv::readUsedCapacity(const QString& deviceNode) const diff --git a/src/fs/nilfs2.cpp b/src/fs/nilfs2.cpp index ffb3a69..5fd15a1 100644 --- a/src/fs/nilfs2.cpp +++ b/src/fs/nilfs2.cpp @@ -96,12 +96,12 @@ FileSystem::SupportTool nilfs2::supportToolName() const qint64 nilfs2::minCapacity() const { - return 128 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 128 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 nilfs2::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int nilfs2::maxLabelLength() const diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index 8164f18..8386275 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -91,12 +91,12 @@ FileSystem::SupportTool ntfs::supportToolName() const qint64 ntfs::minCapacity() const { - return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 2 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 ntfs::maxCapacity() const { - return 256 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); + return 256 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB); } int ntfs::maxLabelLength() const diff --git a/src/fs/ocfs2.cpp b/src/fs/ocfs2.cpp index 040e5b3..1122e64 100644 --- a/src/fs/ocfs2.cpp +++ b/src/fs/ocfs2.cpp @@ -89,12 +89,12 @@ FileSystem::SupportTool ocfs2::supportToolName() const qint64 ocfs2::minCapacity() const { - return 14000 * Capacity::unitFactor(Capacity::Byte, Capacity::KiB); + return 14000 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB); } qint64 ocfs2::maxCapacity() const { - return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::PiB); + return 4 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::PiB); } qint64 ocfs2::readUsedCapacity(const QString& deviceNode) const diff --git a/src/fs/reiser4.cpp b/src/fs/reiser4.cpp index 71d1830..38e1d1e 100644 --- a/src/fs/reiser4.cpp +++ b/src/fs/reiser4.cpp @@ -75,7 +75,7 @@ qint64 reiser4::maxCapacity() const { // looks like it's actually unknown. see // http://en.wikipedia.org/wiki/Comparison_of_file_systems - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int reiser4::maxLabelLength() const diff --git a/src/fs/reiserfs.cpp b/src/fs/reiserfs.cpp index cb78ecf..ddd3de3 100644 --- a/src/fs/reiserfs.cpp +++ b/src/fs/reiserfs.cpp @@ -85,12 +85,12 @@ FileSystem::SupportTool reiserfs::supportToolName() const qint64 reiserfs::minCapacity() const { - return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 reiserfs::maxCapacity() const { - return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 16 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::TiB) - Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } int reiserfs::maxLabelLength() const diff --git a/src/fs/xfs.cpp b/src/fs/xfs.cpp index e0b3339..25d2ef3 100644 --- a/src/fs/xfs.cpp +++ b/src/fs/xfs.cpp @@ -83,12 +83,12 @@ FileSystem::SupportTool xfs::supportToolName() const qint64 xfs::minCapacity() const { - return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 32 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 xfs::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } int xfs::maxLabelLength() const diff --git a/src/fs/zfs.cpp b/src/fs/zfs.cpp index d04de16..a3cb201 100644 --- a/src/fs/zfs.cpp +++ b/src/fs/zfs.cpp @@ -77,12 +77,12 @@ FileSystem::SupportTool zfs::supportToolName() const qint64 zfs::minCapacity() const { - return 64 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); + return 64 * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); } qint64 zfs::maxCapacity() const { - return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); + return Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::EiB); } bool zfs::remove(Report& report, const QString& deviceNode) const diff --git a/src/jobs/resizefilesystemjob.cpp b/src/jobs/resizefilesystemjob.cpp index f27bd70..e308d90 100644 --- a/src/jobs/resizefilesystemjob.cpp +++ b/src/jobs/resizefilesystemjob.cpp @@ -88,7 +88,7 @@ bool ResizeFileSystemJob::run(Report& parent) } case FileSystem::cmdSupportFileSystem: { - const qint64 newLengthInByte = Capacity(newLength() * device().logicalSize()).toInt(Capacity::Byte); + const qint64 newLengthInByte = Capacity(newLength() * device().logicalSize()).toInt(Capacity::Unit::Byte); if (partition().isMounted()) rval = partition().fileSystem().resizeOnline(*report, partition().deviceNode(), partition().mountPoint(), newLengthInByte); else diff --git a/src/jobs/resizevolumegroupjob.cpp b/src/jobs/resizevolumegroupjob.cpp index ae7f37d..3dce190 100644 --- a/src/jobs/resizevolumegroupjob.cpp +++ b/src/jobs/resizevolumegroupjob.cpp @@ -43,9 +43,9 @@ bool ResizeVolumeGroupJob::run(Report& parent) for (const auto &p : partList()) { const QString deviceNode = p->roles().has(PartitionRole::Luks) ? static_cast(&p->fileSystem())->mapperName() : p->partitionPath(); - if (type() == ResizeVolumeGroupJob::Grow) + if (type() == ResizeVolumeGroupJob::Type::Grow) rval = LvmDevice::insertPV(*report, device(), deviceNode); - else if (type() == ResizeVolumeGroupJob::Shrink) + else if (type() == ResizeVolumeGroupJob::Type::Shrink) rval = LvmDevice::removePV(*report, device(), deviceNode); if (rval == false) @@ -66,10 +66,10 @@ QString ResizeVolumeGroupJob::description() const partitionList.chop(2); const qint32 count = partList().count(); - if (type() == ResizeVolumeGroupJob::Grow) { + if (type() == ResizeVolumeGroupJob::Type::Grow) { return xi18ncp("@info/plain", "Adding LVM Physical Volume %2 to %3.", "Adding LVM Physical Volumes %2 to %3.", count, partitionList, device().name()); } - if (type() == ResizeVolumeGroupJob::Shrink) { + if (type() == ResizeVolumeGroupJob::Type::Shrink) { return xi18ncp("@info/plain", "Removing LVM Physical Volume %2 from %3.", "Removing LVM Physical Volumes %2 from %3.", count, partitionList, device().name()); } return xi18nc("@info/plain", "Resizing Volume Group %1 to %2.", device().name(), partitionList); diff --git a/src/jobs/resizevolumegroupjob.h b/src/jobs/resizevolumegroupjob.h index ca5f2de..adb2a1d 100644 --- a/src/jobs/resizevolumegroupjob.h +++ b/src/jobs/resizevolumegroupjob.h @@ -31,9 +31,9 @@ class ResizeVolumeGroupJob : public Job { public: - enum Type { - Grow = 0, - Shrink = 1 + enum class Type { + Grow, + Shrink }; public: diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index 8a9bf59..b0cea05 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -45,13 +45,13 @@ DeleteOperation::DeleteOperation(Device& d, Partition* p, ShredAction shred) : m_DeletePartitionJob(new DeletePartitionJob(targetDevice(), deletedPartition())) { switch (shredAction()) { - case NoShred: + case ShredAction::NoShred: m_DeleteFileSystemJob = static_cast(new DeleteFileSystemJob(targetDevice(), deletedPartition())); break; - case ZeroShred: + case ShredAction::ZeroShred: m_DeleteFileSystemJob = static_cast(new ShredFileSystemJob(targetDevice(), deletedPartition(), false)); break; - case RandomShred: + case ShredAction::RandomShred: m_DeleteFileSystemJob = static_cast(new ShredFileSystemJob(targetDevice(), deletedPartition(), true)); } @@ -89,7 +89,7 @@ void DeleteOperation::undo() QString DeleteOperation::description() const { - if (shredAction() != NoShred) + if (shredAction() != ShredAction::NoShred) return xi18nc("@info:status", "Shred partition %1 (%2, %3)", deletedPartition().deviceNode(), Capacity::formatByteSize(deletedPartition().capacity()), deletedPartition().fileSystem().name()); else return xi18nc("@info:status", "Delete partition %1 (%2, %3)", deletedPartition().deviceNode(), Capacity::formatByteSize(deletedPartition().capacity()), deletedPartition().fileSystem().name()); diff --git a/src/ops/deleteoperation.h b/src/ops/deleteoperation.h index 0796840..682abd2 100644 --- a/src/ops/deleteoperation.h +++ b/src/ops/deleteoperation.h @@ -43,18 +43,18 @@ class LIBKPMCORE_EXPORT DeleteOperation : public Operation Q_DISABLE_COPY(DeleteOperation) public: - enum ShredAction { - NoShred = 0, + enum class ShredAction { + NoShred, ZeroShred, RandomShred }; - DeleteOperation(Device& d, Partition* p, ShredAction shred = NoShred); + DeleteOperation(Device& d, Partition* p, ShredAction shred = ShredAction::NoShred); ~DeleteOperation(); public: QString iconName() const override { - return shredAction() == NoShred ? + return shredAction() == ShredAction::NoShred ? QStringLiteral("edit-delete") : QStringLiteral("edit-delete-shred"); } diff --git a/src/ops/resizevolumegroupoperation.cpp b/src/ops/resizevolumegroupoperation.cpp index d253746..6996899 100644 --- a/src/ops/resizevolumegroupoperation.cpp +++ b/src/ops/resizevolumegroupoperation.cpp @@ -89,12 +89,12 @@ ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& d, const QVect // *DO NOTHING* } else { if (!toInsertList.isEmpty()) { - m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(d, toInsertList, ResizeVolumeGroupJob::Grow); + m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(d, toInsertList, ResizeVolumeGroupJob::Type::Grow); addJob(growVolumeGroupJob()); } if (!toRemoveList.isEmpty()) { m_MovePhysicalVolumeJob = new MovePhysicalVolumeJob(d, toRemoveList); - m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(d, toRemoveList, ResizeVolumeGroupJob::Shrink); + m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(d, toRemoveList, ResizeVolumeGroupJob::Type::Shrink); addJob(movePhysicalVolumeJob()); addJob(shrinkvolumegroupjob()); } diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 0858a75..5d9648d 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -135,7 +135,7 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) modelName = modelName.left(modelName.length() - 1); qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); - Log(Log::information) << xi18nc("@info:status", "Device found: %1", modelName); + Log(Log::Level::information) << xi18nc("@info:status", "Device found: %1", modelName); int logicalSectorSize = sizeCommand2.output().trimmed().toLongLong(); DiskDevice* d = new DiskDevice(modelName, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); diff --git a/src/util/capacity.cpp b/src/util/capacity.cpp index 9e8d6fa..8edde69 100644 --- a/src/util/capacity.cpp +++ b/src/util/capacity.cpp @@ -44,9 +44,9 @@ Capacity::Capacity(const Partition& p, Type t) : m_Size(-1) { switch (t) { - case Used: m_Size = p.used(); break; - case Available: m_Size = p.available(); break; - case Total: m_Size = p.capacity(); + case Type::Used: m_Size = p.used(); break; + case Type::Available: m_Size = p.available(); break; + case Type::Total: m_Size = p.capacity(); } } @@ -64,7 +64,7 @@ Capacity::Capacity(const Device& d) : */ qint64 Capacity::toInt(Unit u) const { - return static_cast(m_Size / unitFactor(Byte, u)); + return static_cast(m_Size / unitFactor(Unit::Byte, u)); } /** Returns the Capacity as double converted to the given Unit. @@ -73,7 +73,7 @@ qint64 Capacity::toInt(Unit u) const */ double Capacity::toDouble(Unit u) const { - return static_cast(m_Size) / unitFactor(Byte, u); + return static_cast(m_Size) / unitFactor(Unit::Byte, u); } /** Returns a factor to convert between two Units. @@ -86,14 +86,14 @@ qint64 Capacity::unitFactor(Unit from, Unit to) Q_ASSERT(from <= to); if (from > to) { - qWarning() << "from: " << from << ", to: " << to; + qWarning() << "from: " << static_cast(from) << ", to: " << static_cast(to); return 1; } qint64 result = 1; - qint32 a = from; - qint32 b = to; + qint32 a = static_cast(from); + qint32 b = static_cast(to); while (b-- > a) result *= 1024; @@ -122,7 +122,7 @@ QString Capacity::unitName(Unit u, qint64 val) if (static_cast(u) >= sizeof(unitNames) / sizeof(unitNames[0])) return xi18nc("@item:intext unit", "(unknown unit)"); - return unitNames[u]; + return unitNames[static_cast(u)]; } /** Determine if the capacity is valid. diff --git a/src/util/capacity.h b/src/util/capacity.h index 023bcfd..bd11bca 100644 --- a/src/util/capacity.h +++ b/src/util/capacity.h @@ -36,16 +36,16 @@ class LIBKPMCORE_EXPORT Capacity { public: /** Units we can deal with */ - enum Unit { Byte, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB }; + enum class Unit : uint { Byte, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB }; /** Type of capacity to print */ - enum Type { Used, Available, Total }; + enum class Type { Used, Available, Total }; /** Flags for printing */ enum Flag { NoFlags = 0, AppendUnit = 1, AppendBytes = 2 }; Q_DECLARE_FLAGS(Flags, Flag) public: explicit Capacity(qint64 size); - explicit Capacity(const Partition& p, Type t = Total); + explicit Capacity(const Partition& p, Type t = Type::Total); Capacity(const Device& d); public: diff --git a/src/util/globallog.h b/src/util/globallog.h index 26eef60..3c1bdaf 100644 --- a/src/util/globallog.h +++ b/src/util/globallog.h @@ -28,15 +28,15 @@ class LIBKPMCORE_EXPORT Log { public: - enum Level { - debug = 0, - information = 1, - warning = 2, - error = 3 + enum class Level { + debug, + information, + warning, + error, }; public: - Log(Level lev = information) : ref(1), level(lev) {} + Log(Level lev = Level::information) : ref(1), level(lev) {} ~Log(); Log(const Log& other) : ref(other.ref + 1), level(other.level) {} diff --git a/test/testsmart.cpp b/test/testsmart.cpp index ad8c098..2236af7 100644 --- a/test/testsmart.cpp +++ b/test/testsmart.cpp @@ -74,7 +74,7 @@ static bool testSmartStatus() if (smart.serial() == QString()) return false; - if (smart.selfTestStatus()) + if (smart.selfTestStatus() != SmartStatus::SelfTestStatus::Success) return false; if (!smart.isValid()) From b5d0b500cfd4f3cd714a2a1209898c95a93d70fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 15:27:07 +0100 Subject: [PATCH 087/175] Reuse SmartStatus::Overall enum for SmartDiskInformation. --- src/core/smartdiskinformation.cpp | 15 +++++++-------- src/core/smartdiskinformation.h | 17 +++++------------ src/core/smartstatus.cpp | 28 +--------------------------- 3 files changed, 13 insertions(+), 47 deletions(-) diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index cc18c7c..3be06cb 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -34,9 +34,8 @@ SmartDiskInformation::SmartDiskInformation() : m_BadAttributeNow(false), m_BadAttributeInThePast(false), m_SelfTestExecutionStatus(SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER), - m_Overall(SmartDiskInformation::Overall::BadStatus) + m_Overall(SmartStatus::Overall::Bad) { - } /** Update the number of bad sectors based on reallocated sector count and current pending sector attributes data */ @@ -62,35 +61,35 @@ void SmartDiskInformation::updateBadSectors() void SmartDiskInformation::updateOverall() { if (!smartStatus()) { - m_Overall = Overall::BadStatus; + m_Overall = SmartStatus::Overall::Bad; return; } quint64 sector_threshold = u64log2(size() / 512) * 1024; if (badSectors() >= sector_threshold) { - m_Overall = Overall::BadSectorsMany; + m_Overall = SmartStatus::Overall::BadSectorsMany; return; } validateBadAttributes(); if (m_BadAttributeNow) { - m_Overall = Overall::BadAttributeNow; + m_Overall = SmartStatus::Overall::BadNow; return; } if (badSectors() > 0) { - m_Overall = Overall::BadSector; + m_Overall = SmartStatus::Overall::BadSectors; return; } if (m_BadAttributeInThePast) { - m_Overall = Overall::BadAttributeInThePast; + m_Overall = SmartStatus::Overall::BadPast; return; } - m_Overall = Overall::Good; + m_Overall = SmartStatus::Overall::Good; } /** Update the temperature value based on SMART attributes diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index 4c55f41..e1593c0 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2018 by Caio Carvalho * + * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -18,6 +19,8 @@ #ifndef KPMCORE_SMARTDISKINFORMATION_H #define KPMCORE_SMARTDISKINFORMATION_H +#include "core/smartstatus.h" + #include #include @@ -47,16 +50,6 @@ public: _SMART_SELF_TEST_EXECUTION_STATUS_MAX }; - /** SMART overall state */ - enum class Overall { - Good, - BadAttributeInThePast, - BadSector, - BadAttributeNow, - BadSectorsMany, - BadStatus, - }; - public: SmartDiskInformation(); @@ -104,7 +97,7 @@ public: return m_SelfTestExecutionStatus; /**< @return SMART self execution status */ } - Overall overall() const + SmartStatus::Overall overall() const { return m_Overall; /**< @return SMART overall status */ } @@ -191,7 +184,7 @@ private: bool m_BadAttributeNow; bool m_BadAttributeInThePast; SmartSelfTestExecutionStatus m_SelfTestExecutionStatus; - Overall m_Overall; + SmartStatus::Overall m_Overall; QList m_Attributes; }; diff --git a/src/core/smartstatus.cpp b/src/core/smartstatus.cpp index 855d99a..0e67cde 100644 --- a/src/core/smartstatus.cpp +++ b/src/core/smartstatus.cpp @@ -115,33 +115,7 @@ void SmartStatus::update() } - switch (disk->overall()) { - case SmartDiskInformation::Overall::Good: - setOverall(Overall::Good); - break; - - case SmartDiskInformation::Overall::BadAttributeInThePast: - setOverall(Overall::BadPast); - break; - - case SmartDiskInformation::Overall::BadSector: - setOverall(Overall::BadSectors); - break; - - case SmartDiskInformation::Overall::BadAttributeNow: - setOverall(Overall::BadNow); - break; - - case SmartDiskInformation::Overall::BadSectorsMany: - setOverall(Overall::BadSectorsMany); - break; - - default: - case SmartDiskInformation::Overall::BadStatus: - setOverall(Overall::Bad); - break; - - } + setOverall(disk->overall()); setTemp(disk->temperature()); From 492e3beb1837e4797c569d3ad48c289eb67b958a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 15:37:46 +0100 Subject: [PATCH 088/175] Reuse SmartStatus::SelfTestStatus enum. --- src/core/smartdiskinformation.cpp | 2 +- src/core/smartdiskinformation.h | 23 ++----------- src/core/smartparser.cpp | 3 +- src/core/smartstatus.cpp | 55 +------------------------------ src/core/smartstatus.h | 2 +- 5 files changed, 7 insertions(+), 78 deletions(-) diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index 3be06cb..1c42d20 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -33,7 +33,7 @@ SmartDiskInformation::SmartDiskInformation() : m_SmartStatus(false), m_BadAttributeNow(false), m_BadAttributeInThePast(false), - m_SelfTestExecutionStatus(SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER), + m_SelfTestExecutionStatus(SmartStatus::SelfTestStatus::Success), m_Overall(SmartStatus::Overall::Bad) { } diff --git a/src/core/smartdiskinformation.h b/src/core/smartdiskinformation.h index e1593c0..dbf3d38 100644 --- a/src/core/smartdiskinformation.h +++ b/src/core/smartdiskinformation.h @@ -34,22 +34,6 @@ class SmartAttributeParsedData; */ class SmartDiskInformation { -public: - /** SMART self test execution state */ - enum SmartSelfTestExecutionStatus { - SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER = 0, - SMART_SELF_TEST_EXECUTION_STATUS_ABORTED = 1, - SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED = 2, - SMART_SELF_TEST_EXECUTION_STATUS_FATAL = 3, - SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN = 4, - SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL = 5, - SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO = 6, - SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ = 7, - SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING = 8, - SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS = 15, - _SMART_SELF_TEST_EXECUTION_STATUS_MAX - }; - public: SmartDiskInformation(); @@ -92,7 +76,7 @@ public: return m_SmartStatus; /**< @return a boolean representing SMART status */ } - SmartSelfTestExecutionStatus selfTestExecutionStatus() const + SmartStatus::SelfTestStatus selfTestExecutionStatus() const { return m_SelfTestExecutionStatus; /**< @return SMART self execution status */ } @@ -158,7 +142,7 @@ public: m_SmartStatus = smartStatus; } - void setSelfTestExecutionStatus(SmartSelfTestExecutionStatus status) + void setSelfTestExecutionStatus(SmartStatus::SelfTestStatus status) { m_SelfTestExecutionStatus = status; } @@ -183,10 +167,9 @@ private: bool m_SmartStatus; bool m_BadAttributeNow; bool m_BadAttributeInThePast; - SmartSelfTestExecutionStatus m_SelfTestExecutionStatus; + SmartStatus::SelfTestStatus m_SelfTestExecutionStatus; SmartStatus::Overall m_Overall; QList m_Attributes; - }; #endif // SMARTDISKINFORMATION_H diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index 4dcf046..7213355 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -91,8 +91,7 @@ bool SmartParser::init() QJsonObject selfTest = smartJson[self_test].toObject(); QJsonObject selfTestStatus = selfTest[status].toObject(); - m_DiskInformation->setSelfTestExecutionStatus((SmartDiskInformation::SmartSelfTestExecutionStatus) - selfTestStatus[value].toInt()); + m_DiskInformation->setSelfTestExecutionStatus(static_cast(selfTestStatus[value].toInt())); loadAttributes(); diff --git a/src/core/smartstatus.cpp b/src/core/smartstatus.cpp index 0e67cde..b9e8e37 100644 --- a/src/core/smartstatus.cpp +++ b/src/core/smartstatus.cpp @@ -64,69 +64,16 @@ void SmartStatus::update() return; setStatus(disk->smartStatus()); - setModelName(disk->model()); - setFirmware(disk->firmware()); - setSerial(disk->serial()); - - switch (disk->selfTestExecutionStatus()) { - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ABORTED: - setSelfTestStatus(SelfTestStatus::Aborted); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED: - setSelfTestStatus(SelfTestStatus::Interrupted); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_FATAL: - setSelfTestStatus(SelfTestStatus::Fatal); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN: - setSelfTestStatus(SelfTestStatus::ErrorUnknown); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL: - setSelfTestStatus(SelfTestStatus::ErrorEletrical); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO: - setSelfTestStatus(SelfTestStatus::ErrorServo); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ: - setSelfTestStatus(SelfTestStatus::ErrorRead); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING: - setSelfTestStatus(SelfTestStatus::ErrorHandling); - break; - - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS: - setSelfTestStatus(SelfTestStatus::InProgress); - break; - - default: - case SmartDiskInformation::SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER: - setSelfTestStatus(SelfTestStatus::Success); - break; - - } - + setSelfTestStatus(disk->selfTestExecutionStatus()); setOverall(disk->overall()); - setTemp(disk->temperature()); - setBadSectors(disk->badSectors()); - setPoweredOn(disk->poweredOn()); - setPowerCycles(disk->powerCycles()); - addAttributes(disk->attributes()); - setInitSuccess(true); } diff --git a/src/core/smartstatus.h b/src/core/smartstatus.h index b54236d..06defe8 100644 --- a/src/core/smartstatus.h +++ b/src/core/smartstatus.h @@ -50,7 +50,7 @@ public: ErrorServo, ErrorRead, ErrorHandling, - InProgress + InProgress = 15, }; public: From a9a637454a7dfe8fb5d6f0db811648086bda3f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 16:07:44 +0100 Subject: [PATCH 089/175] Fix a memory leak in SmartParser. CC: caiojcarvalho@gmail.com --- src/core/smartparser.cpp | 5 +++++ src/core/smartparser.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/core/smartparser.cpp b/src/core/smartparser.cpp index 7213355..294691e 100644 --- a/src/core/smartparser.cpp +++ b/src/core/smartparser.cpp @@ -39,6 +39,11 @@ SmartParser::SmartParser(const QString &device_path) : { } +SmartParser::~SmartParser() +{ + delete m_DiskInformation; +} + /** Initialize SmartParser data, retrieve the information from SMART JSON and initialize the disk information data */ bool SmartParser::init() { diff --git a/src/core/smartparser.h b/src/core/smartparser.h index a48750c..417bd90 100644 --- a/src/core/smartparser.h +++ b/src/core/smartparser.h @@ -33,6 +33,7 @@ class SmartParser { public: SmartParser(const QString &device_path); + ~SmartParser(); public: bool init(); From dda5ddd3e63e33be5b9e3efa6b23c326ecbcecbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 9 Apr 2018 16:16:02 +0100 Subject: [PATCH 090/175] Fix more memory leaks in SmartDiskInformation. --- src/core/smartdiskinformation.cpp | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/core/smartdiskinformation.cpp b/src/core/smartdiskinformation.cpp index 1c42d20..85a5dbb 100644 --- a/src/core/smartdiskinformation.cpp +++ b/src/core/smartdiskinformation.cpp @@ -18,6 +18,8 @@ #include "core/smartdiskinformation.h" #include "core/smartattributeparseddata.h" +#include + static quint64 u64log2(quint64 n); /** Creates a new SmartDiskInformationObject */ @@ -41,11 +43,8 @@ SmartDiskInformation::SmartDiskInformation() : /** Update the number of bad sectors based on reallocated sector count and current pending sector attributes data */ void SmartDiskInformation::updateBadSectors() { - SmartAttributeParsedData *reallocatedSectorCt; - reallocatedSectorCt = findAttribute(5); - - SmartAttributeParsedData *currentPendingSector; - currentPendingSector = findAttribute(197); + std::unique_ptr reallocatedSectorCt(findAttribute(5)); + std::unique_ptr currentPendingSector(findAttribute(197)); if (!reallocatedSectorCt && !currentPendingSector) m_BadSectors = 0; @@ -97,13 +96,9 @@ void SmartDiskInformation::updateOverall() */ bool SmartDiskInformation::updateTemperature() { - SmartAttributeParsedData *temperatureCelsius; - SmartAttributeParsedData *temperatureCelsius2; - SmartAttributeParsedData *airflowTemperatureCelsius; - - temperatureCelsius = findAttribute(231); - temperatureCelsius2 = findAttribute(194); - airflowTemperatureCelsius = findAttribute(190); + std::unique_ptr temperatureCelsius(findAttribute(231)); + std::unique_ptr temperatureCelsius2(findAttribute(194)); + std::unique_ptr airflowTemperatureCelsius(findAttribute(190)); if (temperatureCelsius != nullptr && temperatureCelsius->prettyUnit() == SmartAttributeUnit::Milikelvin) { @@ -127,11 +122,8 @@ bool SmartDiskInformation::updateTemperature() */ bool SmartDiskInformation::updatePowerOn() { - SmartAttributeParsedData *powerOnHours; - SmartAttributeParsedData *powerOnSeconds; - - powerOnHours = findAttribute(9); - powerOnSeconds = findAttribute(233); + std::unique_ptr powerOnHours(findAttribute(9)); + std::unique_ptr powerOnSeconds(findAttribute(233)); if (powerOnHours != nullptr && powerOnHours->prettyUnit() == SmartAttributeUnit::Miliseconds) { @@ -150,9 +142,7 @@ bool SmartDiskInformation::updatePowerOn() */ bool SmartDiskInformation::updatePowerCycle() { - SmartAttributeParsedData *powerCycleCount; - - powerCycleCount = findAttribute(12); + std::unique_ptr powerCycleCount(findAttribute(12)); if (powerCycleCount != nullptr && powerCycleCount->prettyUnit() == SmartAttributeUnit::None) { From 9cc583e7d5e31beae128a397e0277759ec2d1049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 10 Apr 2018 23:26:44 +0300 Subject: [PATCH 091/175] Try to workaround systemd automounting. --- src/core/operationrunner.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/operationrunner.cpp b/src/core/operationrunner.cpp index 1880bf6..9a75b56 100644 --- a/src/core/operationrunner.cpp +++ b/src/core/operationrunner.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * - * Copyright (C) 2016 by Andrius Štikonas * + * Copyright (C) 2016-2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -19,6 +19,8 @@ #include "core/operationrunner.h" #include "core/operationstack.h" #include "ops/operation.h" + +#include "util/externalcommand.h" #include "util/report.h" #include @@ -46,6 +48,11 @@ void OperationRunner::run() bool status = true; + // Disable udev event queue. systemd sometimes likes to automount devices when refreshing partition table + // While this does not prevent automounting, it will at least delay it until partitioning operations are finished + ExternalCommand udevadmStopQueue(report(), QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--stop-exec-queue") }); + udevadmStopQueue.run(); + // Disable Plasma removable device automounting QStringList modules; QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus")); @@ -84,6 +91,9 @@ void OperationRunner::run() if (automounter) kdedInterface.call( QStringLiteral("loadModule"), automounterService ); + ExternalCommand udevadmStartQueue(report(), QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--start-exec-queue") }); + udevadmStartQueue.run(); + if (!status) emit error(); else if (isCancelling()) From db404427440d2383fd7611158392a61643c99285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 11 Apr 2018 03:52:46 +0300 Subject: [PATCH 092/175] d-pointerize Operation class. --- src/core/device.cpp | 2 +- src/ops/operation.cpp | 38 ++++++++++++++++++++++++++++++++++---- src/ops/operation.h | 42 +++++++++++++++++------------------------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/src/core/device.cpp b/src/core/device.cpp index fce2f05..8368633 100644 --- a/src/core/device.cpp +++ b/src/core/device.cpp @@ -54,8 +54,8 @@ Device::Device(std::shared_ptr d_ptr, */ Device::Device(const Device& other) : QObject() + , d(std::make_shared()) { - d = std::make_shared(); d->m_Name = other.d->m_Name; d->m_DeviceNode = other.d->m_DeviceNode; d->m_LogicalSectorSize = other.d->m_LogicalSectorSize; diff --git a/src/ops/operation.cpp b/src/ops/operation.cpp index 8115913..c837f29 100644 --- a/src/ops/operation.cpp +++ b/src/ops/operation.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#include "ops/operation.h" +#include "ops/operation_p.h" #include "core/partition.h" #include "core/device.h" @@ -32,10 +32,10 @@ #include Operation::Operation() : - m_Status(StatusNone), - m_Jobs(), - m_ProgressBase(0) + d(std::make_unique()) { + d->m_Status = StatusNone; + d->m_ProgressBase = 0; } Operation::~Operation() @@ -172,3 +172,33 @@ bool Operation::execute(Report& parent) return rval; } + +Operation::OperationStatus Operation::status() const +{ + return d->m_Status; +} + +void Operation::setStatus(OperationStatus s) +{ + d->m_Status = s; +} + +QList& Operation::jobs() +{ + return d->m_Jobs; +} + +const QList& Operation::jobs() const +{ + return d->m_Jobs; +} + +void Operation::setProgressBase(qint32 i) +{ + d->m_ProgressBase = i; +} + +qint32 Operation::progressBase() const +{ + return d->m_ProgressBase; +} diff --git a/src/ops/operation.h b/src/ops/operation.h index d4dd29f..e551043 100644 --- a/src/ops/operation.h +++ b/src/ops/operation.h @@ -1,5 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2018 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -15,8 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_OPERATION_H) - +#ifndef KPMCORE_OPERATION_H #define KPMCORE_OPERATION_H #include "util/libpartitionmanagerexport.h" @@ -25,10 +25,13 @@ #include #include +#include + class Partition; class Device; -class OperationStack; class Job; +class OperationPrivate; +class OperationStack; class OperationRunner; class Report; @@ -108,17 +111,16 @@ public: virtual bool targets(const Device&) const = 0; virtual bool targets(const Partition&) const = 0; - virtual OperationStatus status() const { - return m_Status; /**< @return the current status */ - } + /**< @return the current status */ + virtual OperationStatus status() const; + virtual QString statusText() const; virtual QString statusIcon() const; - virtual void setStatus(OperationStatus s) { - m_Status = s; /**< @param s the new status */ - } + /**< @param s the new status */ + virtual void setStatus(OperationStatus s); - LIBKPMCORE_EXPORT qint32 totalProgress() const; + qint32 totalProgress() const; protected: void onJobStarted(); @@ -129,24 +131,14 @@ protected: void addJob(Job* job); - QList& jobs() { - return m_Jobs; - } - const QList& jobs() const { - return m_Jobs; - } + QList& jobs(); + const QList& jobs() const; - void setProgressBase(qint32 i) { - m_ProgressBase = i; - } - qint32 progressBase() const { - return m_ProgressBase; - } + void setProgressBase(qint32 i); + qint32 progressBase() const; private: - OperationStatus m_Status; - QList m_Jobs; - qint32 m_ProgressBase; + std::unique_ptr d; }; #endif From 9e107c8136be31ba658deae837055131aaa26c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 11 Apr 2018 15:14:17 +0300 Subject: [PATCH 093/175] Add forgotten files. --- src/fs/filesystem_p.h | 36 ++++++++++++++++++++++++++++++++++++ src/ops/operation_p.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/fs/filesystem_p.h create mode 100644 src/ops/operation_p.h diff --git a/src/fs/filesystem_p.h b/src/fs/filesystem_p.h new file mode 100644 index 0000000..ed410ba --- /dev/null +++ b/src/fs/filesystem_p.h @@ -0,0 +1,36 @@ +/************************************************************************* + * Copyright (C) 2018 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#ifndef KPMCORE_FILESYSTEM_P_H +#define KPMCORE_FILESYSTEM_P_H + +#include "fs/filesystem.h" + +#include + +class FileSystemPrivate { +public: + FileSystem::Type m_Type; + qint64 m_FirstSector; + qint64 m_LastSector; + qint64 m_SectorSize; + qint64 m_SectorsUsed; + QString m_Label; + QString m_UUID; +}; + +#endif diff --git a/src/ops/operation_p.h b/src/ops/operation_p.h new file mode 100644 index 0000000..3a37595 --- /dev/null +++ b/src/ops/operation_p.h @@ -0,0 +1,31 @@ +/************************************************************************* + * Copyright (C) 2018 by Andrius Štikonas * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#ifndef KPMCORE_OPERATION_P_H +#define KPMCORE_OPERATION_P_H + +#include "ops/operation.h" + +class OperationPrivate +{ +public: + Operation::OperationStatus m_Status; + QList m_Jobs; + qint32 m_ProgressBase; +}; + +#endif From 221d7aded6aa391a1b96dd6e32cc5acb18d41425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 12 Apr 2018 00:47:40 +0300 Subject: [PATCH 094/175] d-pointerize ExternalCommand class. --- src/util/capacity.h | 6 +- src/util/externalcommand.cpp | 100 +++++++++++++++++++++++---- src/util/externalcommand.h | 60 ++++++++-------- src/util/libpartitionmanagerexport.h | 8 +-- 4 files changed, 118 insertions(+), 56 deletions(-) diff --git a/src/util/capacity.h b/src/util/capacity.h index bd11bca..632e847 100644 --- a/src/util/capacity.h +++ b/src/util/capacity.h @@ -15,9 +15,9 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_CAPACITY_H) - +#ifndef KPMCORE_CAPACITY_H #define KPMCORE_CAPACITY_H + #include "util/libpartitionmanagerexport.h" class Partition; @@ -40,7 +40,7 @@ public: /** Type of capacity to print */ enum class Type { Used, Available, Total }; /** Flags for printing */ - enum Flag { NoFlags = 0, AppendUnit = 1, AppendBytes = 2 }; + enum class Flag { NoFlags = 0, AppendUnit = 1, AppendBytes = 2 }; Q_DECLARE_FLAGS(Flags, Flag) public: diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 02f60b8..8b67bb6 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -40,17 +40,31 @@ #include #include +struct ExternalCommandPrivate +{ + QVariantMap arguments; + + Report *m_Report; + QString m_Command; + QStringList m_Args; + int m_ExitCode; + QByteArray m_Output; + QByteArray m_Input; +}; + /** Creates a new ExternalCommand instance without Report. @param cmd the command to run @param args the arguments to pass to the command */ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : - m_Report(nullptr), - m_Command(cmd), - m_Args(args), - m_ExitCode(-1), - m_Output() + d(std::make_unique()) { + d->m_Report = nullptr; + d->m_Command = cmd; + d->m_Args = args; + d->m_ExitCode = -1; + d->m_Output = QByteArray(); + setup(processChannelMode); } @@ -60,19 +74,25 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co @param args the arguments to pass to the command */ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : - m_Report(report.newChild()), - m_Command(cmd), - m_Args(args), - m_ExitCode(-1), - m_Output() + d(std::make_unique()) { + d->m_Report = report.newChild(); + d->m_Command = cmd; + d->m_Args = args; + d->m_ExitCode = -1; + d->m_Output = QByteArray(); + setup(processChannelMode); } +ExternalCommand::~ExternalCommand() +{ +} + void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMode) { - arguments.insert(QStringLiteral("environment"), QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); - arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); + d->arguments.insert(QStringLiteral("environment"), QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); + d->arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); // connect(this, qOverload(&QProcess::finished), this, &ExternalCommand::onFinished); // connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); @@ -112,7 +132,7 @@ bool ExternalCommand::start(int timeout) CoreBackendManager::self()->Uuid(), cmd, args(), - m_Input, + d->m_Input, QStringList()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); @@ -127,7 +147,7 @@ bool ExternalCommand::start(int timeout) else { QDBusPendingReply reply = *watcher; - m_Output = reply.value()[QStringLiteral("output")].toByteArray(); + d->m_Output = reply.value()[QStringLiteral("output")].toByteArray(); setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); rval = true; } @@ -188,7 +208,7 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) bool ExternalCommand::write(const QByteArray& input) { - m_Input = input; + d->m_Input = input; return true; } @@ -241,3 +261,53 @@ void ExternalCommand::onFinished(int exitCode, QProcess::ExitStatus exitStatus) Q_UNUSED(exitStatus) setExitCode(exitCode); } + +void ExternalCommand::setCommand(const QString& cmd) +{ + d->m_Command = cmd; +} + +const QString& ExternalCommand::command() const +{ + return d->m_Command; +} + +const QStringList& ExternalCommand::args() const +{ + return d->m_Args; +} + +void ExternalCommand::addArg(const QString& s) +{ + d->m_Args << s; +} + +void ExternalCommand::setArgs(const QStringList& args) +{ + d->m_Args = args; +} + +int ExternalCommand::exitCode() const +{ + return d->m_ExitCode; +} + +const QString ExternalCommand::output() const +{ + return QString::fromLocal8Bit(d->m_Output); +} + +const QByteArray& ExternalCommand::rawOutput() const +{ + return d->m_Output; +} + +Report* ExternalCommand::report() +{ + return d->m_Report; +} + +void ExternalCommand::setExitCode(int i) +{ + d->m_ExitCode = i; +} diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 43b151c..f045f4e 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -16,8 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_EXTERNALCOMMAND_H) - +#ifndef KPMCORE_EXTERNALCOMMAND_H #define KPMCORE_EXTERNALCOMMAND_H #include "util/libpartitionmanagerexport.h" @@ -31,8 +30,11 @@ #include #include +#include + class KJob; class Report; +struct ExternalCommandPrivate; /** An external command. @@ -50,14 +52,24 @@ public: explicit ExternalCommand(const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); explicit ExternalCommand(Report& report, const QString& cmd = QString(), const QStringList& args = QStringList(), const QProcess::ProcessChannelMode processChannelMode = QProcess::MergedChannels); + ~ExternalCommand(); + public: bool copyBlocks(CopySource& source, CopyTarget& target); - void setCommand(const QString& cmd) { m_Command = cmd; } /**< @param cmd the command to run */ - const QString& command() const { return m_Command; } /**< @return the command to run */ - void addArg(const QString& s) { m_Args << s; } /**< @param s the argument to add */ - const QStringList& args() const { return m_Args; } /**< @return the arguments */ - void setArgs(const QStringList& args) { m_Args = args; } /**< @param args the new arguments */ + /**< @param cmd the command to run */ + void setCommand(const QString& cmd); + /**< @return the command to run */ + const QString& command() const; + + /**< @return the arguments */ + const QStringList& args() const; + + /**< @param s the argument to add */ + void addArg(const QString& s); + /**< @param args the new arguments */ + void setArgs(const QStringList& args); + bool write(const QByteArray& input); /**< @param input the input for the program */ bool startCopyBlocks(); @@ -65,21 +77,16 @@ public: bool waitFor(int timeout = 30000); bool run(int timeout = 30000); - int exitCode() const { - return m_ExitCode; /**< @return the exit code */ - } + /**< @return the exit code */ + int exitCode() const; - const QString output() const { - return QString::fromLocal8Bit(m_Output); /**< @return the command output */ - } + /**< @return the command output */ + const QString output() const; + /**< @return the command output */ + const QByteArray& rawOutput() const; - const QByteArray& rawOutput() const { - return m_Output; /**< @return the command output */ - } - - Report* report() { - return m_Report; /**< @return pointer to the Report or nullptr */ - } + /**< @return pointer to the Report or nullptr */ + Report* report(); void emitReport(const QVariantMap& report) { emit reportSignal(report); } @@ -91,23 +98,14 @@ public Q_SLOTS: void emitProgress(KJob*, unsigned long percent) { emit progress(percent); }; protected: - void setExitCode(int i) { - m_ExitCode = i; - } + void setExitCode(int i); void setup(const QProcess::ProcessChannelMode processChannelMode); void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); private: - QVariantMap arguments; - - Report *m_Report; - QString m_Command; - QStringList m_Args; - int m_ExitCode; - QByteArray m_Output; - QByteArray m_Input; + std::unique_ptr d; }; #endif diff --git a/src/util/libpartitionmanagerexport.h b/src/util/libpartitionmanagerexport.h index 457f0e8..9459e65 100644 --- a/src/util/libpartitionmanagerexport.h +++ b/src/util/libpartitionmanagerexport.h @@ -15,15 +15,9 @@ * along with this program. If not, see .* *************************************************************************/ -// #include "libpartitionmanager_export.h" - -#if !defined(KPMCORE_LIBPARTITIONMANAGEREXPORT_H) -#define KPMCORE_LIBPARTITIONMANAGEREXPORT_H +#ifndef LIBKPMCORE_EXPORT #include - -#if !defined(LIBKPMCORE_EXPORT) #define LIBKPMCORE_EXPORT Q_DECL_EXPORT -#endif #endif From 527734e9e8620e4abf3463bd54d5d399771b5e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 12 Apr 2018 15:18:50 +0300 Subject: [PATCH 095/175] Switch JobStatus enum to scoped enum. --- src/jobs/job.cpp | 18 ++++-------------- src/jobs/job.h | 17 ++++++++--------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/jobs/job.cpp b/src/jobs/job.cpp index 8ba23ae..d850b3d 100644 --- a/src/jobs/job.cpp +++ b/src/jobs/job.cpp @@ -35,7 +35,7 @@ Job::Job() : m_Report(nullptr), - m_Status(Pending) + m_Status(Status::Pending) { } @@ -121,7 +121,7 @@ Report* Job::jobStarted(Report& parent) void Job::jobFinished(Report& report, bool b) { - setStatus(b ? Success : Error); + setStatus(b ? Status::Success : Status::Error); emit progress(numSteps()); emit finished(); @@ -137,12 +137,7 @@ QString Job::statusIcon() const QStringLiteral("dialog-error") }; - Q_ASSERT(status() >= 0 && static_cast(status()) < sizeof(icons) / sizeof(icons[0])); - - if (status() < 0 || static_cast(status()) >= sizeof(icons) / sizeof(icons[0])) - return QString(); - - return icons[status()]; + return icons[static_cast(status())]; } /** @return the Job's current status text */ @@ -154,10 +149,5 @@ QString Job::statusText() const xi18nc("@info:progress job", "Error") }; - Q_ASSERT(status() >= 0 && static_cast(status()) < sizeof(s) / sizeof(s[0])); - - if (status() < 0 || static_cast(status()) >= sizeof(s) / sizeof(s[0])) - return QString(); - - return s[status()]; + return s[static_cast(status())]; } diff --git a/src/jobs/job.h b/src/jobs/job.h index b810a0b..e4f9416 100644 --- a/src/jobs/job.h +++ b/src/jobs/job.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_JOB_H) - +#ifndef KPMCORE_JOB_H #define KPMCORE_JOB_H #include "fs/filesystem.h" @@ -49,10 +48,10 @@ class LIBKPMCORE_EXPORT Job : public QObject public: /** Status of this Job */ - enum JobStatus { - Pending = 0, /**< Pending, not yet run */ - Success, /**< Successfully run */ - Error /**< Running generated an error */ + enum class Status : int { + Pending, /**< Pending, not yet run */ + Success, /**< Successfully run */ + Error /**< Running generated an error */ }; protected: @@ -76,7 +75,7 @@ public: virtual QString statusIcon() const; virtual QString statusText() const; - JobStatus status() const { + Status status() const { return m_Status; /**< @return the Job's current status */ } @@ -90,13 +89,13 @@ protected: Report* jobStarted(Report& parent); void jobFinished(Report& report, bool b); - void setStatus(JobStatus s) { + void setStatus(Status s) { m_Status = s; } private: Report *m_Report; - JobStatus m_Status; + Status m_Status; }; #endif From 428ee5b6c88c9c680f58a47570f89745e923c64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 00:43:12 +0300 Subject: [PATCH 096/175] First attempt at using RSA to sign requests to KAuth helper. --- CMakeLists.txt | 2 ++ src/CMakeLists.txt | 3 ++- src/backend/corebackendmanager.cpp | 39 +++++++++++++++++++++++++++++- src/backend/corebackendmanager.h | 8 +++++- src/util/CMakeLists.txt | 1 + src/util/externalcommand.cpp | 19 +++++++++++---- src/util/externalcommandhelper.cpp | 14 +++++++++-- src/util/externalcommandhelper.h | 8 +++--- 8 files changed, 81 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ddb5423..caff811 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,8 @@ find_package(KF5 REQUIRED WidgetsAddons ) +find_package(Qca-qt5 REQUIRED) + # use sane compile flags add_definitions( -DQT_USE_QSTRINGBUILDER diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52ee0b9..500b9a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,12 +42,13 @@ add_library(kpmcore SHARED ${kpmcore_SRCS}) target_link_libraries( kpmcore PUBLIC Qt5::Core PRIVATE + ${BLKID_LIBRARIES} Qt5::DBus Qt5::Gui + qca-qt5 KF5::I18n KF5::CoreAddons KF5::WidgetsAddons - ${BLKID_LIBRARIES} KF5::Auth ) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 62322f2..cd228be 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -40,6 +42,9 @@ struct CoreBackendManagerPrivate CoreBackend *m_Backend; QString m_Uuid; + QCA::Initializer init; + QCA::PrivateKey privateKey; + unsigned int counter = 0; }; CoreBackendManager::CoreBackendManager() : @@ -74,14 +79,34 @@ QVector CoreBackendManager::list() const return KPluginLoader::findPlugins(QString(), filter); } -void CoreBackendManager::startExternalCommandHelper() +bool CoreBackendManager::startExternalCommandHelper() { + // Generate RSA key pair for signing external command requests + if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) { + qCritical() << xi18n("QCA does not support RSA."); + return false; + } + + d->privateKey = QCA::KeyGenerator().createRSA(4096); + if(d->privateKey.isNull()) { + qCritical() << xi18n("Failed to make private RSA key."); + return false; + } + + if (!d->privateKey.canSign()) { + qCritical() << xi18n("Generated key cannot be used for signatures."); + return false; + } + + QCA::PublicKey pubkey = d->privateKey.toPublicKey(); + KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days QVariantMap arguments; d->m_Uuid = QUuid::createUuid().toString(); arguments.insert(QStringLiteral("callerUuid"), Uuid()); + arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); action.setArguments(arguments); d->m_job = action.execute(); job()->start(); @@ -93,6 +118,8 @@ void CoreBackendManager::startExternalCommandHelper() QObject::connect(job(), &KJob::finished, [=] () { if(d->m_job->error()) exitLoop(); } ); loop.exec(); QObject::disconnect(conn); + + return true; } void CoreBackendManager::stopExternalCommandHelper() @@ -145,3 +172,13 @@ bool CoreBackendManager::load(const QString& name) void CoreBackendManager::unload() { } + +QCA::PrivateKey CoreBackendManager::privateKey() +{ + return d->privateKey; +} + +unsigned int& CoreBackendManager::counter() +{ + return d->counter; +} diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index d623b53..70476d7 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -32,6 +32,7 @@ class QStringList; class KPluginMetaData; class CoreBackend; namespace KAuth { class ExecuteJob; } +namespace QCA { class PrivateKey; } struct CoreBackendManagerPrivate; /** @@ -96,8 +97,13 @@ public: */ static void stopExternalCommandHelper(); + /**< @return RSA private key used for signing External Command requests. */ + QCA::PrivateKey privateKey(); + + unsigned int& counter(); + private: - void startExternalCommandHelper(); + bool startExternalCommandHelper(); private: std::unique_ptr d; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 22957f7..6e3abb2 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -25,6 +25,7 @@ qt5_generate_dbus_interface( add_executable(kpmcore_externalcommand util/externalcommandhelper.cpp) target_link_libraries(kpmcore_externalcommand + qca-qt5 Qt5::Core Qt5::DBus KF5::Auth diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 8b67bb6..6b51017 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -25,6 +25,7 @@ #include "util/externalcommand.h" #include "util/report.h" +#include #include #include #include @@ -36,14 +37,14 @@ #include #include +#include + #include #include #include struct ExternalCommandPrivate { - QVariantMap arguments; - Report *m_Report; QString m_Command; QStringList m_Args; @@ -91,8 +92,7 @@ ExternalCommand::~ExternalCommand() void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMode) { - d->arguments.insert(QStringLiteral("environment"), QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); - d->arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); +// d->arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); // FIXME // connect(this, qOverload(&QProcess::finished), this, &ExternalCommand::onFinished); // connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); @@ -128,8 +128,17 @@ bool ExternalCommand::start(int timeout) bool rval = false; if (iface.isValid()) { + QByteArray request; + request.setNum(++CoreBackendManager::self()->counter()); + + request.append(cmd.toUtf8()); + for (const auto &argument : qAsConst(d->m_Args)) + request.append(argument.toLocal8Bit()); + request.append(d->m_Input); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), - CoreBackendManager::self()->Uuid(), + CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), cmd, args(), d->m_Input, diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 0601f23..998ffef 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -40,6 +40,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) return reply; } m_callerUuid = args[QStringLiteral("callerUuid")].toString(); + m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) { qWarning() << QDBusConnection::systemBus().lastError().message(); @@ -196,10 +197,19 @@ bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourc return rval; } -QVariantMap ExternalCommandHelper::start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) +QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) { QVariantMap reply; - if (!isCallerAuthorized(Uuid)) { + + QByteArray request; + request.setNum(++m_Counter); + request.append(command.toLocal8Bit()); + for (const auto &argument : arguments) + request.append(argument.toUtf8()); + request.append(input); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + qCritical() << xi18n("Invalid cryptographic signature"); reply[QStringLiteral("success")] = false; return reply; } diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 299a27e..05d48c1 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -24,7 +24,7 @@ #include #include -class QTimer; +#include using namespace KAuth; @@ -43,7 +43,7 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); - Q_SCRIPTABLE QVariantMap start(const QString& Uuid, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); + Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); @@ -53,11 +53,13 @@ private: QEventLoop m_loop; QString m_callerUuid; + QCA::Initializer initializer; + QCA::PublicKey m_publicKey; + unsigned int m_Counter; QString m_command; QString m_sourceDevice; QProcess m_cmd; - QTimer *timer; // QByteArray output; }; From e0be8fae83efdf935477460422ef0b4b40bc65b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 00:51:08 +0300 Subject: [PATCH 097/175] Initialize m_Counter variable on startup. --- src/util/externalcommandhelper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 998ffef..1f7f14b 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -41,6 +41,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } m_callerUuid = args[QStringLiteral("callerUuid")].toString(); m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); + m_Counter = 0; if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) { qWarning() << QDBusConnection::systemBus().lastError().message(); From fc4133233b50405225dc2b915d99525cc20d3a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 01:06:32 +0300 Subject: [PATCH 098/175] Revert "Try to workaround systemd automounting." This reverts commit 9cc583e7d5e31beae128a397e0277759ec2d1049. --- src/core/operationrunner.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/core/operationrunner.cpp b/src/core/operationrunner.cpp index 9a75b56..1880bf6 100644 --- a/src/core/operationrunner.cpp +++ b/src/core/operationrunner.cpp @@ -1,6 +1,6 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * - * Copyright (C) 2016-2018 by Andrius Štikonas * + * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -19,8 +19,6 @@ #include "core/operationrunner.h" #include "core/operationstack.h" #include "ops/operation.h" - -#include "util/externalcommand.h" #include "util/report.h" #include @@ -48,11 +46,6 @@ void OperationRunner::run() bool status = true; - // Disable udev event queue. systemd sometimes likes to automount devices when refreshing partition table - // While this does not prevent automounting, it will at least delay it until partitioning operations are finished - ExternalCommand udevadmStopQueue(report(), QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--stop-exec-queue") }); - udevadmStopQueue.run(); - // Disable Plasma removable device automounting QStringList modules; QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("sessionBus")); @@ -91,9 +84,6 @@ void OperationRunner::run() if (automounter) kdedInterface.call( QStringLiteral("loadModule"), automounterService ); - ExternalCommand udevadmStartQueue(report(), QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--start-exec-queue") }); - udevadmStartQueue.run(); - if (!status) emit error(); else if (isCancelling()) From 71b56d27a8b771e2287edb5ab4ff4939c5adce19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 01:29:43 +0300 Subject: [PATCH 099/175] Keep Capacity::Unit a simple enum, otherwise KPM fails to compile. --- src/util/capacity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/capacity.h b/src/util/capacity.h index 632e847..1346080 100644 --- a/src/util/capacity.h +++ b/src/util/capacity.h @@ -36,7 +36,7 @@ class LIBKPMCORE_EXPORT Capacity { public: /** Units we can deal with */ - enum class Unit : uint { Byte, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB }; + enum Unit : uint { Byte, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB }; /** Type of capacity to print */ enum class Type { Used, Available, Total }; /** Flags for printing */ From 24e1e83152d7493442bba805068bc5a44e958142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 02:44:12 +0300 Subject: [PATCH 100/175] Try to fix QString encoding issues in KAuth helper. For now set text codec to UTF-8 Needs more investigation if locale of the GUI program is not UTF-8. --- src/util/externalcommand.cpp | 3 +-- src/util/externalcommandhelper.cpp | 8 +++----- src/util/externalcommandhelper.h | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 6b51017..caa4c2c 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -141,8 +141,7 @@ bool ExternalCommand::start(int timeout) CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), cmd, args(), - d->m_Input, - QStringList()); + d->m_Input); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 1f7f14b..02b388c 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -26,9 +26,6 @@ #include -// exit helper if no ping for 42s -#define TIMEOUT 42000 - /** Initialize ExternalCommandHelper Daemon and prepare DBus interface */ ActionReply ExternalCommandHelper::init(const QVariantMap& args) @@ -198,8 +195,9 @@ bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourc return rval; } -QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment) +QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input) { + QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QVariantMap reply; QByteArray request; @@ -217,7 +215,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr // connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); - m_cmd.setEnvironment(environment); + m_cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } ); m_cmd.start(command, arguments); m_cmd.write(input); m_cmd.closeWriteChannel(); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 05d48c1..4795399 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -43,7 +43,7 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); - Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const QStringList& environment); + Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input); Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QString& Uuid); From 6b558f49d8a090046d6ab09bc3302eee8981d78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 13:08:43 +0300 Subject: [PATCH 101/175] Use blockdev --rereadpt instead of partx --update. --- src/jobs/setfilesystemlabeljob.cpp | 2 ++ src/plugins/sfdisk/sfdiskpartitiontable.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/jobs/setfilesystemlabeljob.cpp b/src/jobs/setfilesystemlabeljob.cpp index 7ea7a07..ea1402b 100644 --- a/src/jobs/setfilesystemlabeljob.cpp +++ b/src/jobs/setfilesystemlabeljob.cpp @@ -61,6 +61,8 @@ bool SetFileSystemLabelJob::run(Report& parent) partition().fileSystem().setLabel(label()); } + // FIXME: need to commit to device + jobFinished(*report, rval); return rval; diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 9124107..a33dbc9 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -55,8 +55,8 @@ bool SfdiskPartitionTable::open() bool SfdiskPartitionTable::commit(quint32 timeout) { if ( !(ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("settle"), QStringLiteral("--timeout=") + QString::number(timeout) }).run() && - ExternalCommand(QStringLiteral("partx"), { QStringLiteral("--update"), m_device->deviceNode() }).run()) ) - sleep(timeout); + ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run())) + sleep(1); return true; } From 231bfbd33182a07b754f2fea6b4613e0fa693599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 14:24:05 +0300 Subject: [PATCH 102/175] Cryptographically sign copyblocks and exit KAuth helper calls. --- src/backend/corebackendmanager.cpp | 18 ++++++--------- src/backend/corebackendmanager.h | 7 +----- src/util/externalcommand.cpp | 19 ++++++++++++--- src/util/externalcommandhelper.cpp | 37 ++++++++++++++++++------------ src/util/externalcommandhelper.h | 6 ++--- test/helpers.cpp | 2 +- 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index cd228be..23c4060 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -21,12 +21,12 @@ #include "backend/corebackend.h" #include +#include #include #include #include #include #include -#include #include @@ -41,7 +41,6 @@ struct CoreBackendManagerPrivate KAuth::ExecuteJob *m_job; CoreBackend *m_Backend; - QString m_Uuid; QCA::Initializer init; QCA::PrivateKey privateKey; unsigned int counter = 0; @@ -104,8 +103,6 @@ bool CoreBackendManager::startExternalCommandHelper() action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days QVariantMap arguments; - d->m_Uuid = QUuid::createUuid().toString(); - arguments.insert(QStringLiteral("callerUuid"), Uuid()); arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); action.setArguments(arguments); d->m_job = action.execute(); @@ -125,8 +122,12 @@ bool CoreBackendManager::startExternalCommandHelper() void CoreBackendManager::stopExternalCommandHelper() { QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); - if (iface.isValid()) - iface.call(QStringLiteral("exit"), CoreBackendManager::self()->Uuid()); + if (iface.isValid()) { + QByteArray request; + request.setNum(++CoreBackendManager::self()->counter()); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + iface.call(QStringLiteral("exit"), d->privateKey.signMessage(hash, QCA::EMSA3_Raw)); + } } KAuth::ExecuteJob* CoreBackendManager::job() @@ -134,11 +135,6 @@ KAuth::ExecuteJob* CoreBackendManager::job() return d->m_job; } -QString& CoreBackendManager::Uuid() -{ - return d->m_Uuid; -} - bool CoreBackendManager::load(const QString& name) { if (backend()) diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index 70476d7..07c56eb 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -82,11 +82,6 @@ public: */ CoreBackend* backend(); - /** - * @return a pointer to the currently loaded backend - */ - QString& Uuid(); - /** * @return a pointer to the KAuth job */ @@ -95,7 +90,7 @@ public: /** * stop ExternalCommand Helper */ - static void stopExternalCommandHelper(); + void stopExternalCommandHelper(); /**< @return RSA private key used for signing External Command requests. */ QCA::PrivateKey privateKey(); diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index caa4c2c..a560b30 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -129,12 +129,13 @@ bool ExternalCommand::start(int timeout) bool rval = false; if (iface.isValid()) { QByteArray request; - request.setNum(++CoreBackendManager::self()->counter()); + request.setNum(++CoreBackendManager::self()->counter()); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) - request.append(argument.toLocal8Bit()); + request.append(argument.toUtf8()); request.append(d->m_Input); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), @@ -185,9 +186,21 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { + QByteArray request; + + request.setNum(++CoreBackendManager::self()->counter()); + request.append(source.path().toUtf8()); + request.append(QByteArray::number(source.firstByte())); + request.append(QByteArray::number(source.length())); + request.append(target.path().toUtf8()); + request.append(QByteArray::number(target.firstByte())); + request.append(QByteArray::number(blockSize)); + + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + // Use asynchronous DBus calls, so that we can process reports and progress QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), - CoreBackendManager::self()->Uuid(), + CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 02b388c..713167c 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -36,7 +36,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) reply.addData(QStringLiteral("success"), false); return reply; } - m_callerUuid = args[QStringLiteral("callerUuid")].toString(); m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); m_Counter = 0; @@ -111,10 +110,23 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr return true; } -bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) +bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { - if (!isCallerAuthorized(Uuid)) + QByteArray request; + + request.setNum(++m_Counter); + request.append(sourceDevice.toUtf8()); + request.append(QByteArray::number(sourceFirstByte)); + request.append(QByteArray::number(sourceLength)); + request.append(targetDevice.toUtf8()); + request.append(QByteArray::number(targetFirstByte)); + request.append(QByteArray::number(blockSize)); + + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + qCritical() << xi18n("Invalid cryptographic signature"); return false; + } const qint64 blocksToCopy = sourceLength / blockSize; qint64 readOffset = sourceFirstByte; @@ -202,7 +214,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr QByteArray request; request.setNum(++m_Counter); - request.append(command.toLocal8Bit()); + request.append(command.toUtf8()); for (const auto &argument : arguments) request.append(argument.toUtf8()); request.append(input); @@ -227,20 +239,15 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr return reply; } -bool ExternalCommandHelper::isCallerAuthorized(const QString& Uuid) +void ExternalCommandHelper::exit(const QByteArray& signature) { - if (Uuid != m_callerUuid) { - qWarning() << "Caller is not authorized"; - return false; + QByteArray request; + request.setNum(++m_Counter); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + return; } - return true; -} - -void ExternalCommandHelper::exit(const QString& Uuid) -{ - if (!isCallerAuthorized(Uuid)) - return; m_loop.exit(); if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"))) diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 4795399..818c76c 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -44,15 +44,13 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input); - Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); - Q_SCRIPTABLE void exit(const QString& Uuid); + Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); + Q_SCRIPTABLE void exit(const QByteArray& signature); private: void onReadOutput(); - bool isCallerAuthorized(const QString& Uuid); QEventLoop m_loop; - QString m_callerUuid; QCA::Initializer initializer; QCA::PublicKey m_publicKey; unsigned int m_Counter; diff --git a/test/helpers.cpp b/test/helpers.cpp index e562fce..b89bdd8 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -59,5 +59,5 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ KPMCoreInitializer::~KPMCoreInitializer() { - CoreBackendManager::stopExternalCommandHelper(); + CoreBackendManager::self()->stopExternalCommandHelper(); } From a6100aaa37c06f229243db470303857240670230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 14:26:44 +0300 Subject: [PATCH 103/175] Add an error message in case of invalid signature. --- src/util/externalcommandhelper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 713167c..e1527d4 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -245,6 +245,7 @@ void ExternalCommandHelper::exit(const QByteArray& signature) request.setNum(++m_Counter); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + qCritical() << xi18n("Invalid cryptographic signature"); return; } From 07458efb918dbf2d7df0afc954430b1ece3751bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 15:54:51 +0300 Subject: [PATCH 104/175] Make sure system is informed about the change of file system label. --- src/core/device.h | 1 - src/jobs/setfilesystemlabeljob.cpp | 19 ++++++++++++++++++- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 8 +++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/core/device.h b/src/core/device.h index 5425539..d74184b 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -57,7 +57,6 @@ public: RAID_Device, /* software RAID device */ }; -protected: explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Type::Disk_Device); public: diff --git a/src/jobs/setfilesystemlabeljob.cpp b/src/jobs/setfilesystemlabeljob.cpp index ea1402b..640e275 100644 --- a/src/jobs/setfilesystemlabeljob.cpp +++ b/src/jobs/setfilesystemlabeljob.cpp @@ -18,6 +18,13 @@ #include "jobs/setfilesystemlabeljob.h" +#include "backend/corebackend.h" +#include "backend/corebackendmanager.h" +#include "backend/corebackenddevice.h" +#include "backend/corebackendpartitiontable.h" + +#include "core/device_p.h" +#include "core/operationstack.h" #include "core/partition.h" #include "fs/filesystem.h" @@ -26,6 +33,8 @@ #include +#include + /** Creates a new SetFileSystemLabelJob @param p the Partition the FileSystem whose label is to be set is on @param newlabel the new label @@ -61,7 +70,15 @@ bool SetFileSystemLabelJob::run(Report& parent) partition().fileSystem().setLabel(label()); } - // FIXME: need to commit to device + // A hack to reread partition table (commit() should be called even on non DiskDevices) + Device dev(std::make_shared(), QString(), QString(), 0, 0, QString(), Device::Type::Unknown_Device); + std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(dev); + if (backendDevice) { + std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); + + if (backendPartitionTable) + backendPartitionTable->commit(); + } jobFinished(*report, rval); diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index a33dbc9..0c6ea3d 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -28,8 +28,6 @@ #include "util/report.h" #include "util/externalcommand.h" -#include - #include #include #include @@ -54,9 +52,9 @@ bool SfdiskPartitionTable::open() bool SfdiskPartitionTable::commit(quint32 timeout) { - if ( !(ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("settle"), QStringLiteral("--timeout=") + QString::number(timeout) }).run() && - ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run())) - sleep(1); + ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("settle"), QStringLiteral("--timeout=") + QString::number(timeout) }).run(); + ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run(); + ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("trigger") }).run(); return true; } From ed59aac2c8b58cc2a23ef547cd365e61e0e7a8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 13 Apr 2018 20:21:48 +0300 Subject: [PATCH 105/175] Show error when setting file system label fails. --- src/jobs/setfilesystemlabeljob.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jobs/setfilesystemlabeljob.cpp b/src/jobs/setfilesystemlabeljob.cpp index 640e275..ed17e58 100644 --- a/src/jobs/setfilesystemlabeljob.cpp +++ b/src/jobs/setfilesystemlabeljob.cpp @@ -69,6 +69,8 @@ bool SetFileSystemLabelJob::run(Report& parent) if (rval) partition().fileSystem().setLabel(label()); } + else + rval = false; // A hack to reread partition table (commit() should be called even on non DiskDevices) Device dev(std::make_shared(), QString(), QString(), 0, 0, QString(), Device::Type::Unknown_Device); From 145f54f18ce2100320a51e422c64af4240de8b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 14 Apr 2018 23:55:05 +0300 Subject: [PATCH 106/175] Move KAuth helper setup code to ExternalCommand class. Delay helper startup until it is actually required. --- src/backend/corebackendmanager.cpp | 83 ++---------------------------- src/backend/corebackendmanager.h | 24 +-------- src/util/externalcommand.cpp | 79 +++++++++++++++++++++++++--- src/util/externalcommand.h | 22 ++++++-- test/helpers.cpp | 3 +- test/testdevicescanner.cpp | 13 +++-- test/testlist.cpp | 12 +++-- 7 files changed, 114 insertions(+), 122 deletions(-) diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index 23c4060..bb1fdd2 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -21,16 +21,10 @@ #include "backend/corebackend.h" #include -#include #include -#include -#include #include #include -#include - -#include #include #include #include @@ -38,18 +32,16 @@ struct CoreBackendManagerPrivate { - KAuth::ExecuteJob *m_job; CoreBackend *m_Backend; - - QCA::Initializer init; - QCA::PrivateKey privateKey; - unsigned int counter = 0; }; CoreBackendManager::CoreBackendManager() : d(std::make_unique()) { - startExternalCommandHelper(); +} + +CoreBackendManager::~CoreBackendManager() +{ } CoreBackendManager* CoreBackendManager::self() @@ -78,63 +70,6 @@ QVector CoreBackendManager::list() const return KPluginLoader::findPlugins(QString(), filter); } -bool CoreBackendManager::startExternalCommandHelper() -{ - // Generate RSA key pair for signing external command requests - if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) { - qCritical() << xi18n("QCA does not support RSA."); - return false; - } - - d->privateKey = QCA::KeyGenerator().createRSA(4096); - if(d->privateKey.isNull()) { - qCritical() << xi18n("Failed to make private RSA key."); - return false; - } - - if (!d->privateKey.canSign()) { - qCritical() << xi18n("Generated key cannot be used for signatures."); - return false; - } - - QCA::PublicKey pubkey = d->privateKey.toPublicKey(); - - KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); - action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); - action.setTimeout(10 * 24 * 3600 * 1000); // 10 days - QVariantMap arguments; - arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); - action.setArguments(arguments); - d->m_job = action.execute(); - job()->start(); - - // Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop) - QEventLoop loop; - auto exitLoop = [&] () { loop.exit(); }; - auto conn = QObject::connect(job(), &KAuth::ExecuteJob::newData, exitLoop); - QObject::connect(job(), &KJob::finished, [=] () { if(d->m_job->error()) exitLoop(); } ); - loop.exec(); - QObject::disconnect(conn); - - return true; -} - -void CoreBackendManager::stopExternalCommandHelper() -{ - QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); - if (iface.isValid()) { - QByteArray request; - request.setNum(++CoreBackendManager::self()->counter()); - QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); - iface.call(QStringLiteral("exit"), d->privateKey.signMessage(hash, QCA::EMSA3_Raw)); - } -} - -KAuth::ExecuteJob* CoreBackendManager::job() -{ - return d->m_job; -} - bool CoreBackendManager::load(const QString& name) { if (backend()) @@ -168,13 +103,3 @@ bool CoreBackendManager::load(const QString& name) void CoreBackendManager::unload() { } - -QCA::PrivateKey CoreBackendManager::privateKey() -{ - return d->privateKey; -} - -unsigned int& CoreBackendManager::counter() -{ - return d->counter; -} diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index 07c56eb..45ceaae 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -17,22 +17,18 @@ *************************************************************************/ #ifndef KPMCORE_COREBACKENDMANAGER_H - #define KPMCORE_COREBACKENDMANAGER_H #include "util/libpartitionmanagerexport.h" #include -#include #include class QString; class QStringList; class KPluginMetaData; class CoreBackend; -namespace KAuth { class ExecuteJob; } -namespace QCA { class PrivateKey; } struct CoreBackendManagerPrivate; /** @@ -44,8 +40,8 @@ struct CoreBackendManagerPrivate; */ class LIBKPMCORE_EXPORT CoreBackendManager { -private: CoreBackendManager(); + ~CoreBackendManager(); public: /** @@ -82,24 +78,6 @@ public: */ CoreBackend* backend(); - /** - * @return a pointer to the KAuth job - */ - KAuth::ExecuteJob* job(); - - /** - * stop ExternalCommand Helper - */ - void stopExternalCommandHelper(); - - /**< @return RSA private key used for signing External Command requests. */ - QCA::PrivateKey privateKey(); - - unsigned int& counter(); - -private: - bool startExternalCommandHelper(); - private: std::unique_ptr d; }; diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index a560b30..c62cc15 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -53,6 +53,12 @@ struct ExternalCommandPrivate QByteArray m_Input; }; +unsigned int ExternalCommand::counter = 0; +KAuth::ExecuteJob* ExternalCommand::m_job; +QCA::PrivateKey* ExternalCommand::privateKey; +QCA::Initializer* ExternalCommand::init; +bool ExternalCommand::helperStarted = false; + /** Creates a new ExternalCommand instance without Report. @param cmd the command to run @param args the arguments to pass to the command @@ -66,6 +72,9 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co d->m_ExitCode = -1; d->m_Output = QByteArray(); + if (!helperStarted) + startHelper(); + setup(processChannelMode); } @@ -130,7 +139,7 @@ bool ExternalCommand::start(int timeout) if (iface.isValid()) { QByteArray request; - request.setNum(++CoreBackendManager::self()->counter()); + request.setNum(++counter); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) request.append(argument.toUtf8()); @@ -139,7 +148,7 @@ bool ExternalCommand::start(int timeout) QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), - CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), + privateKey->signMessage(hash, QCA::EMSA3_Raw), cmd, args(), d->m_Input); @@ -180,15 +189,15 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) } // TODO KF6:Use new signal-slot syntax - connect(CoreBackendManager::self()->job(), SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); - connect(CoreBackendManager::self()->job(), &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); + connect(m_job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); + connect(m_job, &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { QByteArray request; - request.setNum(++CoreBackendManager::self()->counter()); + request.setNum(++counter); request.append(source.path().toUtf8()); request.append(QByteArray::number(source.firstByte())); request.append(QByteArray::number(source.length())); @@ -200,7 +209,7 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) // Use asynchronous DBus calls, so that we can process reports and progress QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), - CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), + privateKey->signMessage(hash, QCA::EMSA3_Raw), source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); @@ -332,3 +341,61 @@ void ExternalCommand::setExitCode(int i) { d->m_ExitCode = i; } + +bool ExternalCommand::startHelper() +{ + init = new QCA::Initializer; + // Generate RSA key pair for signing external command requests + if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) { + qCritical() << xi18n("QCA does not support RSA."); + return false; + } + + privateKey = new QCA::PrivateKey; + *privateKey = QCA::KeyGenerator().createRSA(4096); + if(privateKey->isNull()) { + qCritical() << xi18n("Failed to make private RSA key."); + return false; + } + + if (!privateKey->canSign()) { + qCritical() << xi18n("Generated key cannot be used for signatures."); + return false; + } + + QCA::PublicKey pubkey = privateKey->toPublicKey(); + + KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); + action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); + action.setTimeout(10 * 24 * 3600 * 1000); // 10 days + QVariantMap arguments; + arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); + action.setArguments(arguments); + m_job = action.execute(); + m_job->start(); + + // Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop) + QEventLoop loop; + auto exitLoop = [&] () { loop.exit(); }; + auto conn = QObject::connect(m_job, &KAuth::ExecuteJob::newData, exitLoop); + QObject::connect(m_job, &KJob::finished, [=] () { if(m_job->error()) exitLoop(); } ); + loop.exec(); + QObject::disconnect(conn); + + helperStarted = true; + return true; +} + +void ExternalCommand::stopHelper() +{ + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + if (iface.isValid()) { + QByteArray request; + request.setNum(++counter); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw)); + } + + delete privateKey; + delete init; +} diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index f045f4e..c56d84e 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -20,8 +20,6 @@ #define KPMCORE_EXTERNALCOMMAND_H #include "util/libpartitionmanagerexport.h" -#include "core/copysourcedevice.h" -#include "core/copytargetfile.h" #include #include @@ -33,7 +31,11 @@ #include class KJob; +namespace KAuth { class ExecuteJob; } +namespace QCA { class PrivateKey; class Initializer; } class Report; +class CopySource; +class CopyTarget; struct ExternalCommandPrivate; /** An external command. @@ -90,6 +92,13 @@ public: void emitReport(const QVariantMap& report) { emit reportSignal(report); } + // KAuth + /**< start ExternalCommand Helper */ + static bool startHelper(); + + /**< stop ExternalCommand Helper */ + static void stopHelper(); + Q_SIGNALS: void progress(int); void reportSignal(const QVariantMap&); @@ -97,7 +106,7 @@ Q_SIGNALS: public Q_SLOTS: void emitProgress(KJob*, unsigned long percent) { emit progress(percent); }; -protected: +private: void setExitCode(int i); void setup(const QProcess::ProcessChannelMode processChannelMode); @@ -106,6 +115,13 @@ protected: private: std::unique_ptr d; + + // KAuth stuff + static unsigned int counter; + static KAuth::ExecuteJob *m_job; + static QCA::Initializer *init; + static QCA::PrivateKey *privateKey; + static bool helperStarted; }; #endif diff --git a/test/helpers.cpp b/test/helpers.cpp index b89bdd8..9ec2703 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -20,6 +20,7 @@ #include "helpers.h" #include "backend/corebackendmanager.h" +#include "util/externalcommand.h" #include #include @@ -59,5 +60,5 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ KPMCoreInitializer::~KPMCoreInitializer() { - CoreBackendManager::self()->stopExternalCommandHelper(); + ExternalCommand::stopHelper(); } diff --git a/test/testdevicescanner.cpp b/test/testdevicescanner.cpp index d3a39b6..0629e6d 100644 --- a/test/testdevicescanner.cpp +++ b/test/testdevicescanner.cpp @@ -34,6 +34,8 @@ #include #include +#include + using PartitionList = QList; // Recursive helper for flatten(), adds partitions that @@ -65,16 +67,18 @@ PartitionList flatten(PartitionTable *table) int main( int argc, char **argv ) { QCoreApplication app(argc, argv); + std::unique_ptr i; + if (argc != 2) { - KPMCoreInitializer i; - if (!i.isValid()) + i = std::make_unique(); + if (!i->isValid()) return 1; } else { - KPMCoreInitializer i( argv[1] ); - if (!i.isValid()) + i = std::make_unique( argv[1] ); + if (!i->isValid()) return 1; } @@ -112,6 +116,5 @@ int main( int argc, char **argv ) } return 0; - } diff --git a/test/testlist.cpp b/test/testlist.cpp index 6b1c9eb..1960e00 100644 --- a/test/testlist.cpp +++ b/test/testlist.cpp @@ -31,6 +31,8 @@ #include #include +#include + using PartitionList = QList; // Recursive helper for flatten(), adds partitions that @@ -62,17 +64,18 @@ PartitionList flatten(PartitionTable *table) int main( int argc, char **argv ) { QCoreApplication app(argc, argv); + std::unique_ptr i; if (argc != 2) { - KPMCoreInitializer i; - if (!i.isValid()) + i = std::make_unique(); + if (!i->isValid()) return 1; } else { - KPMCoreInitializer i( argv[1] ); - if (!i.isValid()) + i = std::make_unique( argv[1] ); + if (!i->isValid()) return 1; } @@ -105,6 +108,5 @@ int main( int argc, char **argv ) } return 0; - } From 4b1793f79b58a84a3f868f289c432951385dac61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Apr 2018 01:09:48 +0300 Subject: [PATCH 107/175] Update backend name in the docs. --- README.md | 2 +- src/fs/f2fs.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 15e4127..9b16d66 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ of storage devices on a system: There are multiple backends so that KPMcore can support different operating systems, although the only functional backend is the one for Linux systems: -* libparted backend (Linux) +* sfdisk backend (Linux) * null backend ## Using KPMcore diff --git a/src/fs/f2fs.h b/src/fs/f2fs.h index 280fe82..4d2d92b 100644 --- a/src/fs/f2fs.h +++ b/src/fs/f2fs.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_F2FS_H) - +#ifndef KPMCORE_F2FS_H #define KPMCORE_F2FS_H #include "util/libpartitionmanagerexport.h" From 5814c6c02a6616c850d34da90ca9d1390e1de90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Apr 2018 01:35:29 +0300 Subject: [PATCH 108/175] Allow setting KAuth parent widget. --- src/util/externalcommand.cpp | 3 +++ src/util/externalcommand.h | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index c62cc15..a165913 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -58,6 +58,8 @@ KAuth::ExecuteJob* ExternalCommand::m_job; QCA::PrivateKey* ExternalCommand::privateKey; QCA::Initializer* ExternalCommand::init; bool ExternalCommand::helperStarted = false; +QWidget* ExternalCommand::parent; + /** Creates a new ExternalCommand instance without Report. @param cmd the command to run @@ -368,6 +370,7 @@ bool ExternalCommand::startHelper() KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days + action.setParentWidget(parent); QVariantMap arguments; arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); action.setArguments(arguments); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index c56d84e..b260b10 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -99,6 +99,13 @@ public: /**< stop ExternalCommand Helper */ static void stopHelper(); + /**< Sets a parent widget for the authentication dialog. + * @param p parent widget + */ + static void setParentWidget(QWidget *p) { + parent = p; + } + Q_SIGNALS: void progress(int); void reportSignal(const QVariantMap&); @@ -122,6 +129,7 @@ private: static QCA::Initializer *init; static QCA::PrivateKey *privateKey; static bool helperStarted; + static QWidget *parent; }; #endif From 99c14ad074bfcaeba15ddc73405b25144e7a9861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 16 Apr 2018 11:06:13 +0300 Subject: [PATCH 109/175] Correctly report when excutable is not found. --- src/fs/filesystem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index df6eb8c..bac502c 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -564,6 +564,8 @@ bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, i QString cmdFullPath = QStandardPaths::findExecutable(cmdName); if (cmdFullPath.isEmpty()) cmdFullPath = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); + if (cmdFullPath.isEmpty()) + return false; ExternalCommand cmd(cmdFullPath, args); if (!cmd.run()) From a43d5bbc5b37de0b3e7ea9b424ee9a6db6eb473f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 16 Apr 2018 11:32:29 +0300 Subject: [PATCH 110/175] fatresize is libparted based, so does not support FAT12. --- src/fs/fat12.h | 7 +++---- src/fs/fat16.h | 10 ++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/fs/fat12.h b/src/fs/fat12.h index ef8818f..5a02895 100644 --- a/src/fs/fat12.h +++ b/src/fs/fat12.h @@ -16,8 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_FAT12_H) - +#ifndef KPMCORE_FAT12_H #define KPMCORE_FAT12_H #include "util/libpartitionmanagerexport.h" @@ -62,10 +61,10 @@ public: return m_Create; } CommandSupportType supportGrow() const override { - return m_Grow; + return cmdSupportNone; } CommandSupportType supportShrink() const override { - return m_Shrink; + return cmdSupportNone; } CommandSupportType supportMove() const override { return m_Move; diff --git a/src/fs/fat16.h b/src/fs/fat16.h index a654431..ea988a5 100644 --- a/src/fs/fat16.h +++ b/src/fs/fat16.h @@ -16,8 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_FAT16_H) - +#ifndef KPMCORE_FAT16_H #define KPMCORE_FAT16_H #include "fs/fat12.h" @@ -43,6 +42,13 @@ public: bool create(Report& report, const QString& deviceNode) override; bool resize(Report& report, const QString& deviceNode, qint64 length) const override; + CommandSupportType supportGrow() const override { + return m_Grow; + } + CommandSupportType supportShrink() const override { + return m_Shrink; + } + qint64 minCapacity() const override; qint64 maxCapacity() const override; bool supportToolFound() const override; From 0d29dc8a6b86c3f531e93206e2c4f65ff86b4fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 18 Apr 2018 21:46:15 +0300 Subject: [PATCH 111/175] Fix class/struct mismatch in forward declaration. --- src/backend/corebackend.h | 2 +- src/gui/partwidget.cpp | 4 ++-- src/util/helpers.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/corebackend.h b/src/backend/corebackend.h index 6a61b34..386d67f 100644 --- a/src/backend/corebackend.h +++ b/src/backend/corebackend.h @@ -30,7 +30,7 @@ class CoreBackendManager; class CoreBackendDevice; -class CoreBackendPrivate; +struct CoreBackendPrivate; class Device; class PartitionTable; diff --git a/src/gui/partwidget.cpp b/src/gui/partwidget.cpp index d728c23..57ebf23 100644 --- a/src/gui/partwidget.cpp +++ b/src/gui/partwidget.cpp @@ -21,10 +21,10 @@ #include "fs/filesystem.h" #include "util/capacity.h" -#include -#include #include #include +#include +#include /** Creates a new PartWidget @param parent pointer to the parent widget diff --git a/src/util/helpers.cpp b/src/util/helpers.cpp index 6f1e3fb..6f2cfc9 100644 --- a/src/util/helpers.cpp +++ b/src/util/helpers.cpp @@ -56,7 +56,7 @@ KAboutData aboutKPMcore() KAboutData aboutData( QStringLiteral("kpmcore"), xi18nc("@title", "KPMcore"), QStringLiteral(VERSION), xi18nc("@title", "Library for managing partitions"), - KAboutLicense::GPL_V3, xi18nc("@info:credit", "© 2008-2017 KPMcore developers" ) ); + KAboutLicense::GPL_V3, xi18nc("@info:credit", "© 2008-2018 KPMcore developers" ) ); aboutData.setOrganizationDomain(QByteArray("kde.org")); aboutData.setProductName(QByteArray("kpmcore")); aboutData.setHomepage(QStringLiteral("https://commits.kde.org/kpmcore")); From ea664bfffcbe4ca14a13c3fdc100a7e1a17cc5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Apr 2018 21:34:24 +0300 Subject: [PATCH 112/175] Set polkit action icon to partitionmanager. --- src/util/org.kde.kpmcore.externalcommand.actions | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/org.kde.kpmcore.externalcommand.actions b/src/util/org.kde.kpmcore.externalcommand.actions index 0e69798..b60f6ee 100644 --- a/src/util/org.kde.kpmcore.externalcommand.actions +++ b/src/util/org.kde.kpmcore.externalcommand.actions @@ -1,3 +1,6 @@ +[Domain] +Icon=partitionmanager + [org.kde.kpmcore.externalcommand.init] Name=Start external command daemon Description=Root privileges are needed to manage disks From dcfb9f181fe6353c11708f03b72f8468aae3157c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 23 Apr 2018 00:09:46 +0300 Subject: [PATCH 113/175] Use more C++11 initializer lists. --- src/core/lvmdevice.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index d3a8b51..b32733b 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -435,8 +435,7 @@ bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList& if (FS::lvm2_pv::getAllocatedPE(pvPath) <= 0) return true; - QStringList args = QStringList(); - args << QStringLiteral("pvmove"); + QStringList args = { QStringLiteral("pvmove") }; args << pvPath; if (!destinations.isEmpty()) for (const auto &destPath : destinations) @@ -448,8 +447,7 @@ bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList& bool LvmDevice::createVG(Report& report, const QString vgName, const QVector& pvList, const qint32 peSize) { - QStringList args = QStringList(); - args << QStringLiteral("vgcreate") << QStringLiteral("--physicalextentsize") << QString::number(peSize); + QStringList args = { QStringLiteral("vgcreate"), QStringLiteral("--physicalextentsize"), QString::number(peSize) }; args << vgName; for (const auto &p : pvList) { if (p->roles().has(PartitionRole::Luks)) From 40f59a487027b27eb5d04971fae8213792fb0733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 23 Apr 2018 11:05:44 +0300 Subject: [PATCH 114/175] Rename LUKS open and close Labels to "Lock" and "Unlock" BUG: 393409 --- src/fs/luks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index 224c27d..ebd37e6 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -169,12 +169,12 @@ QString luks::unmountTitle() const QString luks::cryptOpenTitle() const { - return xi18nc("@title:menu", "Decrypt"); + return xi18nc("@title:menu", "Unlock"); } QString luks::cryptCloseTitle() const { - return xi18nc("@title:menu", "Deactivate"); + return xi18nc("@title:menu", "Lock"); } void luks::setPassphrase(const QString& passphrase) From c791e4546ca584e5db312327a55fd145af6a9dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 23 Apr 2018 14:18:20 +0300 Subject: [PATCH 115/175] Remove findLIBPARTED.cmake --- cmake/modules/FindLIBPARTED.cmake | 57 ------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 cmake/modules/FindLIBPARTED.cmake diff --git a/cmake/modules/FindLIBPARTED.cmake b/cmake/modules/FindLIBPARTED.cmake deleted file mode 100644 index b689b40..0000000 --- a/cmake/modules/FindLIBPARTED.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2008,2010,2011 by Volker Lanz -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -include(CheckCSourceCompiles) -include(CheckFunctionExists) - -if (LIBPARTED_INCLUDE_DIR AND LIBPARTED_LIBRARY) - # Already in cache, be silent - set(LIBPARTED_FIND_QUIETLY TRUE) -endif (LIBPARTED_INCLUDE_DIR AND LIBPARTED_LIBRARY) - - -FIND_PATH(LIBPARTED_INCLUDE_DIR parted.h PATH_SUFFIXES parted ) - -FIND_LIBRARY(LIBPARTED_LIBRARY NAMES parted) -FIND_LIBRARY(LIBPARTED_FS_RESIZE_LIBRARY NAMES parted-fs-resize) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPARTED DEFAULT_MSG LIBPARTED_LIBRARY LIBPARTED_INCLUDE_DIR) - -if (LIBPARTED_FS_RESIZE_LIBRARY) - set(LIBPARTED_LIBS ${LIBPARTED_FS_RESIZE_LIBRARY} ${LIBPARTED_LIBRARY}) -else (LIBPARTED_FS_RESIZE_LIBRARY) - set(LIBPARTED_LIBS ${LIBPARTED_LIBRARY}) -endif (LIBPARTED_FS_RESIZE_LIBRARY) - -# KDE adds -ansi to the C make flags, parted headers use GNU extensions, so -# undo that -unset(CMAKE_C_FLAGS) - -set(CMAKE_REQUIRED_INCLUDES ${LIBPARTED_INCLUDE_DIR}) -set(CMAKE_REQUIRED_LIBRARIES ${LIBPARTED_LIBS}) - -CHECK_FUNCTION_EXISTS("ped_file_system_clobber" LIBPARTED_FILESYSTEM_SUPPORT) # parted < 3.0 -CHECK_FUNCTION_EXISTS("ped_file_system_resize" LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) # parted != 3.0 - -MARK_AS_ADVANCED(LIBPARTED_LIBRARY LIBPARTED_INCLUDE_DIR LIBPARTED_FILESYSTEM_SUPPORT LIBPARTED_FS_RESIZE_LIBRARY LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT) From 34cfc63da48dd57ded0815a28bd2f94ef55a94c1 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Thu, 3 May 2018 20:48:11 -0300 Subject: [PATCH 116/175] Including CreateVolumeGroupOperation::targets(const Partition&) implementation. --- src/ops/createvolumegroupoperation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ops/createvolumegroupoperation.cpp b/src/ops/createvolumegroupoperation.cpp index 8771bc0..90c4826 100644 --- a/src/ops/createvolumegroupoperation.cpp +++ b/src/ops/createvolumegroupoperation.cpp @@ -45,8 +45,12 @@ QString CreateVolumeGroupOperation::description() const return xi18nc("@info/plain", "Create a new LVM volume group."); } -bool CreateVolumeGroupOperation::targets(const Partition&) const +bool CreateVolumeGroupOperation::targets(const Partition& partition) const { + for (const auto &p : m_PVList) { + if (partition == *p) + return true; + } return false; } From 1e95d01923e7d363ea7fe6e68d5280ec58bc64ef Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 7 May 2018 21:55:49 -0300 Subject: [PATCH 117/175] - Including vgName in CreateVolumeGroupOperation description. - Don't delete LVM PVs that are being targeted by CreateVolumeGroupOperations. - Don't shrink or move LVM PVs that are being targeted by CreateVolumeGroupOperations. --- src/ops/createvolumegroupoperation.cpp | 5 +-- src/ops/createvolumegroupoperation.h | 1 + src/ops/deleteoperation.cpp | 23 ++++++++++++- src/ops/deleteoperation.h | 2 +- src/ops/resizeoperation.cpp | 46 ++++++++++++++++++++++++-- src/ops/resizeoperation.h | 4 +-- 6 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/ops/createvolumegroupoperation.cpp b/src/ops/createvolumegroupoperation.cpp index 90c4826..5930905 100644 --- a/src/ops/createvolumegroupoperation.cpp +++ b/src/ops/createvolumegroupoperation.cpp @@ -35,14 +35,15 @@ CreateVolumeGroupOperation::CreateVolumeGroupOperation(const QString& vgName, const QVector& pvList, const qint32 peSize) : Operation(), m_CreateVolumeGroupJob(new CreateVolumeGroupJob(vgName, pvList, peSize)), - m_PVList(pvList) + m_PVList(pvList), + m_vgName(vgName) { addJob(createVolumeGroupJob()); } QString CreateVolumeGroupOperation::description() const { - return xi18nc("@info/plain", "Create a new LVM volume group."); + return xi18nc("@info/plain", "Create a new LVM volume group named \'%1\'.", m_vgName); } bool CreateVolumeGroupOperation::targets(const Partition& partition) const diff --git a/src/ops/createvolumegroupoperation.h b/src/ops/createvolumegroupoperation.h index c75c45c..4fa49f2 100644 --- a/src/ops/createvolumegroupoperation.h +++ b/src/ops/createvolumegroupoperation.h @@ -69,6 +69,7 @@ protected: private: CreateVolumeGroupJob* m_CreateVolumeGroupJob; const QVector m_PVList; + QString m_vgName; }; #endif diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index b0cea05..768051c 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see .* *************************************************************************/ +#include "ops/createvolumegroupoperation.h" #include "ops/deleteoperation.h" #include "core/partition.h" @@ -110,7 +111,7 @@ void DeleteOperation::checkAdjustLogicalNumbers(Partition& p, bool undo) @param p the Partition in question, may be nullptr. @return true if @p p can be deleted. */ -bool DeleteOperation::canDelete(const Partition* p) +bool DeleteOperation::canDelete(const Partition* p, const QList pendingOps) { if (p == nullptr) return false; @@ -118,6 +119,26 @@ bool DeleteOperation::canDelete(const Partition* p) if (p->isMounted()) return false; + if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { + // See if innerFS is LVM + FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + } + if (p->roles().has(PartitionRole::Unallocated)) return false; diff --git a/src/ops/deleteoperation.h b/src/ops/deleteoperation.h index 682abd2..39faccd 100644 --- a/src/ops/deleteoperation.h +++ b/src/ops/deleteoperation.h @@ -68,7 +68,7 @@ public: bool targets(const Device& d) const override; bool targets(const Partition& p) const override; - static bool canDelete(const Partition* p); + static bool canDelete(const Partition* p, const QList pendingOps = QList()); protected: Device& targetDevice() { diff --git a/src/ops/resizeoperation.cpp b/src/ops/resizeoperation.cpp index 3bac007..57b7361 100644 --- a/src/ops/resizeoperation.cpp +++ b/src/ops/resizeoperation.cpp @@ -30,8 +30,10 @@ #include "jobs/movefilesystemjob.h" #include "ops/checkoperation.h" +#include "ops/createvolumegroupoperation.h" #include "fs/filesystem.h" +#include "fs/luks.h" #include "util/capacity.h" #include "util/report.h" @@ -346,11 +348,31 @@ bool ResizeOperation::canGrow(const Partition* p) @param p the Partition in question, may be nullptr. @return true if @p p can be shrunk. */ -bool ResizeOperation::canShrink(const Partition* p) +bool ResizeOperation::canShrink(const Partition* p, const QList pendingOps) { if (p == nullptr) return false; + if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { + // See if innerFS is LVM + FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + } + // we can always grow, shrink or move a partition not yet written to disk if (p->state() == Partition::State::New && !p->roles().has(PartitionRole::Luks)) return true; @@ -368,11 +390,31 @@ bool ResizeOperation::canShrink(const Partition* p) @param p the Partition in question, may be nullptr. @return true if @p p can be moved. */ -bool ResizeOperation::canMove(const Partition* p) +bool ResizeOperation::canMove(const Partition* p, const QList pendingOps) { if (p == nullptr) return false; + if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { + // See if innerFS is LVM + FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } + } + } + // we can always grow, shrink or move a partition not yet written to disk if (p->state() == Partition::State::New) // too many bad things can happen for LUKS partitions diff --git a/src/ops/resizeoperation.h b/src/ops/resizeoperation.h index e620b5a..820edc7 100644 --- a/src/ops/resizeoperation.h +++ b/src/ops/resizeoperation.h @@ -86,8 +86,8 @@ public: bool targets(const Partition& p) const override; static bool canGrow(const Partition* p); - static bool canShrink(const Partition* p); - static bool canMove(const Partition* p); + static bool canShrink(const Partition* p, const QList pendingOps = QList()); + static bool canMove(const Partition* p, const QList pendingOps = QList()); protected: Device& targetDevice() { From 6b0af70ccdbc10bd118ce39cd09806624f714830 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 7 May 2018 22:56:24 -0300 Subject: [PATCH 118/175] Avoiding segfault in DeleteOperation and ResizeOperation. --- src/ops/deleteoperation.cpp | 14 ++++++++------ src/ops/resizeoperation.cpp | 28 ++++++++++++++++------------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index 768051c..f0168e4 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -128,13 +128,15 @@ bool DeleteOperation::canDelete(const Partition* p, const QList pen } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM - FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); - if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; + if (fs) { + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } } } } diff --git a/src/ops/resizeoperation.cpp b/src/ops/resizeoperation.cpp index 57b7361..8c44f7b 100644 --- a/src/ops/resizeoperation.cpp +++ b/src/ops/resizeoperation.cpp @@ -362,13 +362,15 @@ bool ResizeOperation::canShrink(const Partition* p, const QList pen } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM - FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); - if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; + if (fs) { + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } } } } @@ -404,13 +406,15 @@ bool ResizeOperation::canMove(const Partition* p, const QList pendi } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM - FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); - if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; + if (fs) { + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return false; + } } } } From 9e6cf4063a29dd13fafed939e2ee4ae3061a37d6 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Wed, 9 May 2018 04:09:17 -0300 Subject: [PATCH 119/175] - Refactoring LVM::pvList to be a class with static QList attribute instead of extern instance. - Moving LVM VG verification in canShrink, canMove, canGrow to isLVMPVinNewlyVG method at ResizeOperation. - Don't grow LVM PVs that are being targeted by CreateVolumeGroupOperations. --- src/core/lvmdevice.cpp | 9 +++-- src/fs/luks.cpp | 4 +- src/fs/lvm2_pv.cpp | 6 ++- src/fs/lvm2_pv.h | 17 +++++++- src/ops/deleteoperation.cpp | 2 +- src/ops/resizeoperation.cpp | 78 +++++++++++++++++-------------------- src/ops/resizeoperation.h | 5 ++- 7 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index b32733b..90cf852 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -196,18 +196,19 @@ void LvmDevice::scanSystemLVM(QList& devices) lvmList.append(new LvmDevice(vgName)); } - // Some LVM operations require additional information about LVM physical volumes which we store in LVM::pvList - LVM::pvList = FS::lvm2_pv::getPVs(devices); + // Some LVM operations require additional information about LVM physical volumes which we store in LVM::pvList::list() + LVM::pvList::list().clear(); + LVM::pvList::list().append(FS::lvm2_pv::getPVs(devices)); // Look for LVM physical volumes in LVM VGs for (const auto &d : lvmList) { devices.append(d); - LVM::pvList.append(FS::lvm2_pv::getPVinNode(d->partitionTable())); + LVM::pvList::list().append(FS::lvm2_pv::getPVinNode(d->partitionTable())); } // Inform LvmDevice about which physical volumes form that particular LvmDevice for (const auto &d : lvmList) - for (const auto &p : qAsConst(LVM::pvList)) + for (const auto &p : qAsConst(LVM::pvList::list())) if (p.vgName() == d->name()) d->physicalVolumes().append(p.partition()); diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index ebd37e6..a79b0f9 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -287,7 +287,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) if (!m_isCryptOpen) return false; - for (auto &p : LVM::pvList) + for (auto &p : LVM::pvList::list()) if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Type::Lvm2_PV) p.setLuks(false); @@ -326,7 +326,7 @@ bool luks::cryptClose(const QString& deviceNode) m_isCryptOpen = (m_innerFs != nullptr); - for (auto &p : LVM::pvList) + for (auto &p : LVM::pvList::list()) if (!p.isLuks() && p.partition()->deviceNode() == deviceNode) p.setLuks(true); diff --git a/src/fs/lvm2_pv.cpp b/src/fs/lvm2_pv.cpp index 92778e6..6a3a4c7 100644 --- a/src/fs/lvm2_pv.cpp +++ b/src/fs/lvm2_pv.cpp @@ -296,7 +296,11 @@ QList lvm2_pv::getPVs(const QList& devices) } -QList LVM::pvList; +namespace LVM { + +QList pvList::m_list; + +} LvmPV::LvmPV(const QString vgName, const Partition* p, bool isLuks) : m_vgName(vgName) diff --git a/src/fs/lvm2_pv.h b/src/fs/lvm2_pv.h index 895d26e..15bbd92 100644 --- a/src/fs/lvm2_pv.h +++ b/src/fs/lvm2_pv.h @@ -62,7 +62,22 @@ private: }; namespace LVM { - extern LIBKPMCORE_EXPORT QList pvList; +/** Class to access a global LVM PV list. + @author Caio Carvalho +*/ +class LIBKPMCORE_EXPORT pvList +{ +public: + static QList &list() { + return m_list; + } + +private: + pvList() { } + +private: + static QList m_list; +}; } namespace FS diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index f0168e4..3f2c52f 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -128,7 +128,7 @@ bool DeleteOperation::canDelete(const Partition* p, const QList pen } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM - FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); + FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); if (fs) { if (fs->type() == FileSystem::Type::Lvm2_PV) { diff --git a/src/ops/resizeoperation.cpp b/src/ops/resizeoperation.cpp index 8c44f7b..d73df26 100644 --- a/src/ops/resizeoperation.cpp +++ b/src/ops/resizeoperation.cpp @@ -329,11 +329,14 @@ bool ResizeOperation::grow(Report& report) @param p the Partition in question, may be nullptr. @return true if @p p can be grown. */ -bool ResizeOperation::canGrow(const Partition* p) +bool ResizeOperation::canGrow(const Partition* p, const QList pendingOps) { if (p == nullptr) return false; + if (isLVMPVinNewlyVG(p, pendingOps)) + return false; + // we can always grow, shrink or move a partition not yet written to disk if (p->state() == Partition::State::New && !p->roles().has(PartitionRole::Luks)) return true; @@ -353,27 +356,8 @@ bool ResizeOperation::canShrink(const Partition* p, const QList pen if (p == nullptr) return false; - if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } - } - else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { - // See if innerFS is LVM - FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); - - if (fs) { - if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } - } - } - } + if (isLVMPVinNewlyVG(p, pendingOps)) + return false; // we can always grow, shrink or move a partition not yet written to disk if (p->state() == Partition::State::New && !p->roles().has(PartitionRole::Luks)) @@ -397,27 +381,8 @@ bool ResizeOperation::canMove(const Partition* p, const QList pendi if (p == nullptr) return false; - if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } - } - else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { - // See if innerFS is LVM - FileSystem *fs = dynamic_cast(&p->fileSystem())->innerFS(); - - if (fs) { - if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } - } - } - } + if (isLVMPVinNewlyVG(p, pendingOps)) + return false; // we can always grow, shrink or move a partition not yet written to disk if (p->state() == Partition::State::New) @@ -433,3 +398,30 @@ bool ResizeOperation::canMove(const Partition* p, const QList pendi return p->fileSystem().supportMove() != FileSystem::cmdSupportNone; } + +bool ResizeOperation::isLVMPVinNewlyVG(const Partition *p, const QList pendingOps) +{ + if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return true; + } + } + else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { + // See if innerFS is LVM + FileSystem *fs = static_cast(&p->fileSystem())->innerFS(); + + if (fs) { + if (fs->type() == FileSystem::Type::Lvm2_PV) { + // See if there is a newly created VG targeting this partition + for (Operation *op : qAsConst(pendingOps)) { + if (dynamic_cast(op) && op->targets(*p)) + return true; + } + } + } + } + + return false; +} diff --git a/src/ops/resizeoperation.h b/src/ops/resizeoperation.h index 820edc7..975d08f 100644 --- a/src/ops/resizeoperation.h +++ b/src/ops/resizeoperation.h @@ -85,7 +85,7 @@ public: bool targets(const Device& d) const override; bool targets(const Partition& p) const override; - static bool canGrow(const Partition* p); + static bool canGrow(const Partition* p, const QList pendingOps = QList()); static bool canShrink(const Partition* p, const QList pendingOps = QList()); static bool canMove(const Partition* p, const QList pendingOps = QList()); @@ -158,6 +158,9 @@ protected: return m_CheckResizedJob; } +private: + static bool isLVMPVinNewlyVG(const Partition* p, const QList pendingOps); + private: Device& m_TargetDevice; Partition& m_Partition; From 858c0d660bba528eca4b033b491338d588a0f3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 8 Jun 2018 11:25:29 +0100 Subject: [PATCH 120/175] Drop soversion in a branch. There won't be any release on master branch before merging kauth branch. master already had soversion bump after the last release. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index caff811..139e94c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ set(VERSION_MAJOR "3") set(VERSION_MINOR "3") set(VERSION_RELEASE "0") set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}) -set(SOVERSION "9") +set(SOVERSION "8") add_definitions(-D'VERSION="${VERSION}"') #" set(CMAKE_CXX_STANDARD 14) From 83847a705e7dfee0f98c2cc6a8e0360387d6ed7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 8 Jun 2018 11:30:28 +0100 Subject: [PATCH 121/175] Bump blkid requirement to 2.31.1 We actually need 2.32 for all features but at least 2.31.1 contains most fixes and has already propagated to most distros. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 139e94c..30f1eb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ kde_enable_exceptions() if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(PkgConfig REQUIRED) - pkg_check_modules(BLKID REQUIRED blkid>=2.30) + pkg_check_modules(BLKID REQUIRED blkid>=2.31.1) endif() include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/) From 0dd5ac25fd96024265515e9992c8e034840aa1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 16 Jun 2018 19:35:09 +0100 Subject: [PATCH 122/175] Revert "Remove deprecated attribute for now." This reverts commit 4bcf9288e672d3ae7717f95d921358322805e336. --- src/core/partition.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/partition.h b/src/core/partition.h index c675c10..63f604d 100644 --- a/src/core/partition.h +++ b/src/core/partition.h @@ -80,10 +80,10 @@ public: New, /**< from a NewOperation */ Copy, /**< from a CopyOperation */ Restore, /**< from a RestoreOperation */ - StateNone = None, - StateNew = New, - StateCopy = Copy, - StateRestore = Restore + StateNone __attribute__((deprecated("Use Partition::State::None"))) = None, + StateNew __attribute__((deprecated("Use Partition::State::New"))) = New, + StateCopy __attribute__((deprecated("Use Partition::State::Copy"))) = Copy, + StateRestore __attribute__((deprecated("Use Partition::State::Restore"))) = Restore }; Partition(PartitionNode* parent, const Device& device, const PartitionRole& role, FileSystem* fs, qint64 sectorStart, qint64 sectorEnd, QString partitionPath, PartitionTable::Flags availableFlags = PartitionTable::FlagNone, const QString& mountPoint = QString(), bool mounted = false, PartitionTable::Flags activeFlags = PartitionTable::FlagNone, State state = State::None); From 9e3386a53b0e398a61b28f1800c8b4b9f1c7b01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 8 Jul 2018 11:02:34 +0100 Subject: [PATCH 123/175] Static cast should be sufficient here In the line above we already check if partition type is luks --- src/ops/deleteoperation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index 3f2c52f..0a83c96 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -149,7 +149,7 @@ bool DeleteOperation::canDelete(const Partition* p, const QList pen if (p->roles().has(PartitionRole::Luks)) { - const FS::luks* luksFs = dynamic_cast(&p->fileSystem()); + const FS::luks* luksFs = static_cast(&p->fileSystem()); if (!luksFs) return false; From 998b1292c0231ed612e1f31a1ed430bf8d4a0cc2 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 9 Jul 2018 20:01:34 -0300 Subject: [PATCH 124/175] SoftwareRAID initial implementation. --- src/core/CMakeLists.txt | 2 + src/core/device.h | 3 +- src/core/softwareraid.cpp | 216 +++++++++++++++++++++++++++ src/core/softwareraid.h | 74 +++++++++ src/plugins/sfdisk/sfdiskbackend.cpp | 143 ++++++++++++------ src/plugins/sfdisk/sfdiskbackend.h | 1 + 6 files changed, 391 insertions(+), 48 deletions(-) create mode 100644 src/core/softwareraid.cpp create mode 100644 src/core/softwareraid.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 504890a..21e3a0b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -23,6 +23,7 @@ set(CORE_SRC core/smartparser.cpp core/smartattributeparseddata.cpp core/smartdiskinformation.cpp + core/softwareraid.cpp core/volumemanagerdevice.cpp ) @@ -41,5 +42,6 @@ set(CORE_LIB_HDRS core/partitiontable.h core/smartattribute.h core/smartstatus.h + core/softwareraid.h core/volumemanagerdevice.h ) diff --git a/src/core/device.h b/src/core/device.h index d74184b..7efe179 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -54,7 +54,8 @@ public: Unknown_Device, Disk_Device, LVM_Device, /* VG */ - RAID_Device, /* software RAID device */ + SoftwareRAID_Device, /* software RAID device, i.e. mdraid */ + HardwareRAID_Device, /* hardware RAID device (or fake raid), i.e. dmraid */ }; explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Type::Disk_Device); diff --git a/src/core/softwareraid.cpp b/src/core/softwareraid.cpp new file mode 100644 index 0000000..e2779c0 --- /dev/null +++ b/src/core/softwareraid.cpp @@ -0,0 +1,216 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "softwareraid.h" + +#include "backend/corebackend.h" +#include "backend/corebackendmanager.h" +#include "core/partition.h" +#include "core/volumemanagerdevice_p.h" +#include "fs/filesystem.h" +#include "fs/filesystemfactory.h" +#include "util/externalcommand.h" + +#include + +#define d_ptr std::static_pointer_cast(d) + +class SoftwareRAIDPrivate : public VolumeManagerDevicePrivate +{ +public: + qint32 m_raidLevel; + qint64 m_chunkSize; + qint64 m_totalChunk; + qint64 m_arraySize; + QString m_UUID; + QStringList m_devicePathList; +}; + +SoftwareRAID::SoftwareRAID(const QString& name, const QString& iconName) + : VolumeManagerDevice(std::make_shared(), + name, + (QStringLiteral("/dev/") + name), + getChunkSize(QStringLiteral("/dev/") + name), + getTotalChunk(QStringLiteral("/dev/") + name), + iconName, + Device::Type::SoftwareRAID_Device) +{ + d_ptr->m_raidLevel = getRaidLevel(deviceNode()); + d_ptr->m_chunkSize = logicalSize(); + d_ptr->m_totalChunk = totalLogical(); + d_ptr->m_arraySize = getArraySize(deviceNode()); + d_ptr->m_UUID = getUUID(deviceNode()); + d_ptr->m_devicePathList = getDevicePathList(deviceNode()); + + initPartitions(); +} + +const QStringList SoftwareRAID::deviceNodes() const +{ + return d_ptr->m_devicePathList; +} + +const QStringList& SoftwareRAID::partitionNodes() const +{ + return {}; +} + +qint64 SoftwareRAID::partitionSize(QString &partitionPath) const +{ + Q_UNUSED(partitionPath); + return 0; +} + +bool SoftwareRAID::growArray(Report &report, const QStringList &devices) +{ + Q_UNUSED(report); + Q_UNUSED(devices); + return false; +} + +bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) +{ + Q_UNUSED(report); + Q_UNUSED(devices); + return false; +} + +void SoftwareRAID::scanSoftwareRAID(QList& devices) +{ + ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); + + if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { + QRegularExpression re(QStringLiteral("md(\\d+)\\s+:")); + QRegularExpressionMatchIterator i = re.globalMatch(scanRaid.output()); + while (i.hasNext()) { + QRegularExpressionMatch reMatch = i.next(); + + QString deviceNode = QStringLiteral("/dev/") + QStringLiteral("md") + reMatch.captured(1).trimmed(); + + Device* d = CoreBackendManager::self()->backend()->scanDevice(deviceNode); + + if ( d ) + devices << d; + } + } +} + +qint32 SoftwareRAID::getRaidLevel(const QString &path) +{ + QString output = getDetail(path); + + if (!output.isEmpty()) { + QRegularExpression re(QStringLiteral("Raid Level :\\s+\\w+(\\d+)")); + QRegularExpressionMatch reMatch = re.match(output); + if (reMatch.hasMatch()) + return reMatch.captured(1).toLongLong(); + } + + return -1; +} + +qint64 SoftwareRAID::getChunkSize(const QString &path) +{ + QString output = getDetail(path); + if (!output.isEmpty()) { + QRegularExpression re(QStringLiteral("Chunk Size :\\s+(\\d+)")); + QRegularExpressionMatch reMatch = re.match(output); + if (reMatch.hasMatch()) + return reMatch.captured(1).toLongLong() * 1024; + } + return -1; + +} + +qint64 SoftwareRAID::getTotalChunk(const QString &path) +{ + return getArraySize(path) / getChunkSize(path); +} + +qint64 SoftwareRAID::getArraySize(const QString &path) +{ + QString output = getDetail(path); + if (!output.isEmpty()) { + QRegularExpression re(QStringLiteral("Array Size :\\s+(\\d+)")); + QRegularExpressionMatch reMatch = re.match(output); + if (reMatch.hasMatch()) + return reMatch.captured(1).toLongLong() * 1024; + } + return -1; + +} + +QString SoftwareRAID::getUUID(const QString &path) +{ + Q_UNUSED(path); + return QStringLiteral(); +} + +QStringList SoftwareRAID::getDevicePathList(const QString &path) +{ + Q_UNUSED(path); + return {}; +} + +bool SoftwareRAID::createSoftwareRAID(Report &report, + const QString &name, + const QStringList devicePathList, + const qint32 raidLevel, + const qint32 chunkSize) +{ + return false; +} + +bool SoftwareRAID::deleteSoftwareRAID(Report &report, + SoftwareRAID &raidDevice) +{ + Q_UNUSED(report); + Q_UNUSED(raidDevice); + return false; +} + +bool SoftwareRAID::assembleSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) +{ + Q_UNUSED(report); + Q_UNUSED(raidDevice); + return false; +} + +bool SoftwareRAID::stopSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) +{ + Q_UNUSED(report); + Q_UNUSED(raidDevice); + return false; +} + +void SoftwareRAID::initPartitions() +{ + +} + +qint64 SoftwareRAID::mappedSector(const QString &partitionPath, qint64 sector) const +{ + return -1; +} + +QString SoftwareRAID::getDetail(const QString &path) +{ + ExternalCommand cmd(QStringLiteral("mdadm"), + { QStringLiteral("--detail"), + path }); + return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QStringLiteral(); +} diff --git a/src/core/softwareraid.h b/src/core/softwareraid.h new file mode 100644 index 0000000..eab9eb6 --- /dev/null +++ b/src/core/softwareraid.h @@ -0,0 +1,74 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#if !defined(KPMCORE_SOFTWARERAID_H) +#define KPMCORE_SOFTWARERAID_H + +#include "core/volumemanagerdevice.h" +#include "util/libpartitionmanagerexport.h" +#include "util/report.h" + +class LIBKPMCORE_EXPORT SoftwareRAID : public VolumeManagerDevice +{ + Q_DISABLE_COPY(SoftwareRAID) + +public: + SoftwareRAID(const QString& name, const QString& iconName = QString()); + + const QStringList deviceNodes() const override; + const QStringList& partitionNodes() const override; + qint64 partitionSize(QString &partitionPath) const override; + + virtual bool growArray(Report& report, const QStringList& devices); + + virtual bool shrinkArray(Report& report, const QStringList& devices); + +public: + static void scanSoftwareRAID(QList& devices); + + static qint32 getRaidLevel(const QString& path); + static qint64 getChunkSize(const QString& path); + static qint64 getTotalChunk(const QString& path); + static qint64 getArraySize(const QString& path); + static QString getUUID(const QString& path); + static QStringList getDevicePathList(const QString& path); + + static bool createSoftwareRAID(Report& report, + const QString& name, + const QStringList devicePathList, + const qint32 raidLevel, + const qint32 chunkSize); + + static bool deleteSoftwareRAID(Report& report, + SoftwareRAID& raidDevice); + + static bool assembleSoftwareRAID(Report& report, + const SoftwareRAID& raidDevice); + + static bool stopSoftwareRAID(Report& report, + const SoftwareRAID& raidDevice); + +protected: + void initPartitions() override; + + qint64 mappedSector(const QString &partitionPath, qint64 sector) const override; + +private: + static QString getDetail(const QString& path); +}; + +#endif // SOFTWARERAID_H diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 33f8ed0..9989ee8 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -23,6 +23,7 @@ #include "core/diskdevice.h" #include "core/lvmdevice.h" +#include "core/softwareraid.h" #include "core/partitiontable.h" #include "core/partitionalignment.h" @@ -106,6 +107,7 @@ QList SfdiskBackend::scanDevices(bool excludeReadOnly) } LvmDevice::scanSystemLVM(result); + SoftwareRAID::scanSoftwareRAID(result); } return result; @@ -126,61 +128,50 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) ExternalCommand sizeCommand2(QStringLiteral("blockdev"), { QStringLiteral("--getss"), deviceNode }); ExternalCommand jsonCommand(QStringLiteral("sfdisk"), { QStringLiteral("--json"), deviceNode } ); - if ( modelCommand.run(-1) && modelCommand.exitCode() == 0 - && sizeCommand.run(-1) && sizeCommand.exitCode() == 0 - && sizeCommand2.run(-1) && sizeCommand2.exitCode() == 0 - && jsonCommand.run(-1) ) + if ( sizeCommand.run(-1) && sizeCommand.exitCode() == 0 + && sizeCommand2.run(-1) && sizeCommand2.exitCode() == 0 + && jsonCommand.run(-1) ) { - QString modelName = modelCommand.output(); - modelName = modelName.left(modelName.length() - 1); + Device* d = nullptr; qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); - - Log(Log::Level::information) << xi18nc("@info:status", "Device found: %1", modelName); int logicalSectorSize = sizeCommand2.output().trimmed().toLongLong(); - DiskDevice* d = new DiskDevice(modelName, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); - if (jsonCommand.exitCode() != 0) - return d; - - const QJsonObject jsonObject = QJsonDocument::fromJson(jsonCommand.rawOutput()).object(); - const QJsonObject partitionTable = jsonObject[QLatin1String("partitiontable")].toObject(); - - QString tableType = partitionTable[QLatin1String("label")].toString(); - const PartitionTable::TableType type = PartitionTable::nameToTableType(tableType); - - qint64 firstUsableSector = 0, lastUsableSector = d->totalSectors(); - if (type == PartitionTable::gpt) { - firstUsableSector = partitionTable[QLatin1String("firstlba")].toVariant().toLongLong(); - lastUsableSector = partitionTable[QLatin1String("lastlba")].toVariant().toLongLong(); - } - if (lastUsableSector < firstUsableSector) { - return nullptr; - } - - setPartitionTableForDevice(*d, new PartitionTable(type, firstUsableSector, lastUsableSector)); - switch (type) { - case PartitionTable::gpt: + if ( modelCommand.run(-1) && modelCommand.exitCode() == 0 && !modelCommand.output().trimmed().isEmpty() ) { - // Read the maximum number of GPT partitions - qint32 maxEntries; - ExternalCommand ddCommand(QStringLiteral("dd"), { QStringLiteral("skip=1"), QStringLiteral("count=1"), QStringLiteral("if=") + deviceNode}, QProcess::SeparateChannels); - if (ddCommand.run(-1) && ddCommand.exitCode() == 0 ) { - QByteArray gptHeader = ddCommand.rawOutput(); - QByteArray gptMaxEntries = gptHeader.mid(80, 4); - QDataStream stream(&gptMaxEntries, QIODevice::ReadOnly); - stream.setByteOrder(QDataStream::LittleEndian); - stream >> maxEntries; - } - else - maxEntries = 128; - CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), maxEntries); + QString modelName = modelCommand.output(); + modelName = modelName.left(modelName.length() - 1); + + Log(Log::Level::information) << xi18nc("@info:status", "Disk Device found: %1", modelName); + + d = new DiskDevice(modelName, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); } - default: - break; + else // check for software raid + { + ExternalCommand softwareRaidCommand(QStringLiteral("mdadm"), { QStringLiteral("--detail"), deviceNode }); + + if ( softwareRaidCommand.run(-1) && softwareRaidCommand.exitCode() == 0 ) + { + Log(Log::Level::information) << xi18nc("@info:status", "Software RAID Device found: %1", deviceNode); + + QString deviceName = deviceNode.mid(5); + + d = new SoftwareRAID( deviceName ); + } } - scanDevicePartitions(*d, partitionTable[QLatin1String("partitions")].toArray()); - return d; + if ( d ) + { + if (jsonCommand.exitCode() != 0) + return d; + + const QJsonObject jsonObject = QJsonDocument::fromJson(jsonCommand.rawOutput()).object(); + const QJsonObject partitionTable = jsonObject[QLatin1String("partitiontable")].toObject(); + + if (!updateDevicePartitionTable(*d, partitionTable)) + return nullptr; + + return d; + } } else { @@ -291,6 +282,64 @@ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartit PartitionAlignment::isAligned(d, *part); } +bool SfdiskBackend::updateDevicePartitionTable(Device &d, const QJsonObject &jsonPartitionTable) +{ + QString tableType = jsonPartitionTable[QLatin1String("label")].toString(); + const PartitionTable::TableType type = PartitionTable::nameToTableType(tableType); + + qint64 firstUsableSector = 0, lastUsableSector; + + if ( d.type() == Device::Type::Disk_Device ) + { + const DiskDevice* diskDevice = static_cast(&d); + + lastUsableSector = diskDevice->totalSectors(); + } + else if ( d.type() == Device::Type::SoftwareRAID_Device ) + { + const SoftwareRAID* raidDevice = static_cast(&d); + + lastUsableSector = raidDevice->totalLogical() - 1; + } + + if (type == PartitionTable::gpt) { + firstUsableSector = jsonPartitionTable[QLatin1String("firstlba")].toVariant().toLongLong(); + lastUsableSector = jsonPartitionTable[QLatin1String("lastlba")].toVariant().toLongLong(); + } + + if (lastUsableSector < firstUsableSector) { + return false; + } + + setPartitionTableForDevice(d, new PartitionTable(type, firstUsableSector, lastUsableSector)); + switch (type) { + case PartitionTable::gpt: + { + // Read the maximum number of GPT partitions + qint32 maxEntries; + ExternalCommand ddCommand(QStringLiteral("dd"), + { QStringLiteral("skip=1"), QStringLiteral("count=1"), (QStringLiteral("if=") + d.deviceNode()) }, + QProcess::SeparateChannels); + if (ddCommand.run(-1) && ddCommand.exitCode() == 0 ) { + QByteArray gptHeader = ddCommand.rawOutput(); + QByteArray gptMaxEntries = gptHeader.mid(80, 4); + QDataStream stream(&gptMaxEntries, QIODevice::ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream >> maxEntries; + } + else + maxEntries = 128; + CoreBackend::setPartitionTableMaxPrimaries(*d.partitionTable(), maxEntries); + } + default: + break; + } + + scanDevicePartitions(d, jsonPartitionTable[QLatin1String("partitions")].toArray()); + + return true; +} + /** Reads the sectors used in a FileSystem and stores the result in the Partition's FileSystem object. @param p the Partition the FileSystem is on @param mountPoint mount point of the partition in question diff --git a/src/plugins/sfdisk/sfdiskbackend.h b/src/plugins/sfdisk/sfdiskbackend.h index d60deb1..dcc7952 100644 --- a/src/plugins/sfdisk/sfdiskbackend.h +++ b/src/plugins/sfdisk/sfdiskbackend.h @@ -58,6 +58,7 @@ public: private: static void readSectorsUsed(const Device& d, Partition& p, const QString& mountPoint); void scanDevicePartitions(Device& d, const QJsonArray& jsonPartitions); + bool updateDevicePartitionTable(Device& d, const QJsonObject& jsonPartitionTable); static PartitionTable::Flags availableFlags(PartitionTable::TableType type); }; From c03c0ddc157558b48d8456f1217bf8c6196f71f0 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 9 Jul 2018 20:48:52 -0300 Subject: [PATCH 125/175] Including src/core/raid subdirectory. --- src/core/CMakeLists.txt | 6 ++++-- src/core/raid/CMakeLists.txt | 7 +++++++ src/core/{ => raid}/softwareraid.cpp | 0 src/core/{ => raid}/softwareraid.h | 0 src/plugins/sfdisk/sfdiskbackend.cpp | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/core/raid/CMakeLists.txt rename src/core/{ => raid}/softwareraid.cpp (100%) rename src/core/{ => raid}/softwareraid.h (100%) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 21e3a0b..719ec3a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,3 +1,5 @@ +include(core/raid/CMakeLists.txt) + set(CORE_SRC core/copysource.cpp core/copysourcedevice.cpp @@ -23,8 +25,8 @@ set(CORE_SRC core/smartparser.cpp core/smartattributeparseddata.cpp core/smartdiskinformation.cpp - core/softwareraid.cpp core/volumemanagerdevice.cpp + ${RAID_SRC} ) set(CORE_LIB_HDRS @@ -42,6 +44,6 @@ set(CORE_LIB_HDRS core/partitiontable.h core/smartattribute.h core/smartstatus.h - core/softwareraid.h core/volumemanagerdevice.h + ${RAID_LIB_HDRS} ) diff --git a/src/core/raid/CMakeLists.txt b/src/core/raid/CMakeLists.txt new file mode 100644 index 0000000..d2e18f1 --- /dev/null +++ b/src/core/raid/CMakeLists.txt @@ -0,0 +1,7 @@ +set(RAID_SRC + core/raid/softwareraid.cpp +) + +set(RAID_LIB_HDRS + core/raid/softwareraid.h +) diff --git a/src/core/softwareraid.cpp b/src/core/raid/softwareraid.cpp similarity index 100% rename from src/core/softwareraid.cpp rename to src/core/raid/softwareraid.cpp diff --git a/src/core/softwareraid.h b/src/core/raid/softwareraid.h similarity index 100% rename from src/core/softwareraid.h rename to src/core/raid/softwareraid.h diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 9989ee8..fed674e 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -23,9 +23,9 @@ #include "core/diskdevice.h" #include "core/lvmdevice.h" -#include "core/softwareraid.h" #include "core/partitiontable.h" #include "core/partitionalignment.h" +#include "core/raid/softwareraid.h" #include "fs/filesystemfactory.h" #include "fs/luks.h" From 04a5e2914d0c0d60dea6995ad9ef651f67200d13 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 10 Jul 2018 19:09:22 -0300 Subject: [PATCH 126/175] Correctly showing Software RAID device partition table. --- src/core/partitiontable.cpp | 2 +- src/core/raid/softwareraid.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/partitiontable.cpp b/src/core/partitiontable.cpp index acc2080..e9a1979 100644 --- a/src/core/partitiontable.cpp +++ b/src/core/partitiontable.cpp @@ -295,7 +295,7 @@ bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent, } return end - start + 1 >= PartitionAlignment::sectorAlignment(device); - } else if (d.type() == Device::Type::LVM_Device) { + } else if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device) { if (end - start + 1 > 0) { return true; } diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index e2779c0..c1725d0 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -130,7 +130,7 @@ qint64 SoftwareRAID::getChunkSize(const QString &path) QRegularExpression re(QStringLiteral("Chunk Size :\\s+(\\d+)")); QRegularExpressionMatch reMatch = re.match(output); if (reMatch.hasMatch()) - return reMatch.captured(1).toLongLong() * 1024; + return reMatch.captured(1).toLongLong(); } return -1; From 6c27d99f2c5c14ce75ae703d697515c55242b506 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 10 Jul 2018 20:03:59 -0300 Subject: [PATCH 127/175] Enabling to create and delete SoftwareRAID devices' partitions. --- src/jobs/createpartitionjob.cpp | 2 +- src/jobs/deletepartitionjob.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jobs/createpartitionjob.cpp b/src/jobs/createpartitionjob.cpp index 820b527..e6fb374 100644 --- a/src/jobs/createpartitionjob.cpp +++ b/src/jobs/createpartitionjob.cpp @@ -50,7 +50,7 @@ bool CreatePartitionJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Type::Disk_Device) { + if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { diff --git a/src/jobs/deletepartitionjob.cpp b/src/jobs/deletepartitionjob.cpp index 07c30ff..9ba59bc 100644 --- a/src/jobs/deletepartitionjob.cpp +++ b/src/jobs/deletepartitionjob.cpp @@ -57,7 +57,7 @@ bool DeletePartitionJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Type::Disk_Device) { + if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { From ae8987b82cbd79ed91f9cc988e426fd01c3cef53 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 10 Jul 2018 23:03:21 -0300 Subject: [PATCH 128/175] Sfdisk always creates RAID logical partitions with a 'p' character before partition number. --- src/core/raid/softwareraid.cpp | 5 +++++ src/core/raid/softwareraid.h | 2 ++ src/plugins/sfdisk/sfdiskpartitiontable.cpp | 5 ++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index c1725d0..883947e 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -166,6 +166,11 @@ QStringList SoftwareRAID::getDevicePathList(const QString &path) return {}; } +bool SoftwareRAID::isRaidPath(const QString &path) +{ + return !getDetail(path).isEmpty(); +} + bool SoftwareRAID::createSoftwareRAID(Report &report, const QString &name, const QStringList devicePathList, diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index eab9eb6..641350f 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -47,6 +47,8 @@ public: static QString getUUID(const QString& path); static QStringList getDevicePathList(const QString& path); + static bool isRaidPath(const QString& path); + static bool createSoftwareRAID(Report& report, const QString& name, const QStringList devicePathList, diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 0c6ea3d..c169a8c 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -22,6 +22,7 @@ #include "core/partition.h" #include "core/device.h" +#include "core/raid/softwareraid.h" #include "fs/filesystem.h" @@ -77,8 +78,10 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { QRegularExpression re(QStringLiteral("Created a new partition (\\d)")); QRegularExpressionMatch rem = re.match(createCommand.output()); + + // TODO: Needs refactoring. Workaround to check if device path is RAID and include 'p' character before partition number. if (rem.hasMatch()) - return partition.devicePath() + rem.captured(1); + return partition.devicePath() + (SoftwareRAID::isRaidPath(partition.devicePath()) ? QStringLiteral("p") : QStringLiteral("")) + rem.captured(1); } report.line() << xi18nc("@info:progress", "Failed to add partition %1 to device %2.", partition.deviceNode(), m_device->deviceNode()); From a8b7222350c2e1b81a6778d214efc7c099bf03a1 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 10 Jul 2018 23:04:55 -0300 Subject: [PATCH 129/175] Check for SoftwareRAID devices in CreateFileSystemJob. --- src/jobs/createfilesystemjob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jobs/createfilesystemjob.cpp b/src/jobs/createfilesystemjob.cpp index 264f219..6a285d2 100644 --- a/src/jobs/createfilesystemjob.cpp +++ b/src/jobs/createfilesystemjob.cpp @@ -59,7 +59,7 @@ bool CreateFileSystemJob::run(Report& parent) else createResult = partition().fileSystem().create(*report, partition().deviceNode()); if (createResult) { - if (device().type() == Device::Type::Disk_Device) { + if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { From ab7def5e7d932b0df67823bd194ceeaf8ad05a88 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Wed, 11 Jul 2018 11:57:56 -0300 Subject: [PATCH 130/175] Changing HardwareRAID_Device to FakeRAID_Device. --- src/core/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/device.h b/src/core/device.h index 7efe179..68c40e3 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -55,7 +55,7 @@ public: Disk_Device, LVM_Device, /* VG */ SoftwareRAID_Device, /* software RAID device, i.e. mdraid */ - HardwareRAID_Device, /* hardware RAID device (or fake raid), i.e. dmraid */ + FakeRAID_Device, /* fake RAID device, i.e. dmraid */ }; explicit Device(std::shared_ptr d_ptr, const QString& name, const QString& deviceNode, const qint64 logicalSectorSize, const qint64 totalLogicalSectors, const QString& iconName = QString(), Device::Type type = Device::Type::Disk_Device); From a2d601d512e8b6d4c8c42d5b5fced264eb703247 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Wed, 11 Jul 2018 12:01:26 -0300 Subject: [PATCH 131/175] Checking for SoftwareRAID_Device type in partition table job. --- src/core/partitiontable.cpp | 2 +- src/jobs/createpartitiontablejob.cpp | 2 +- src/jobs/setpartgeometryjob.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/partitiontable.cpp b/src/core/partitiontable.cpp index e9a1979..f5a4322 100644 --- a/src/core/partitiontable.cpp +++ b/src/core/partitiontable.cpp @@ -428,7 +428,7 @@ void PartitionTable::updateUnallocated(const Device& d) qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t) { Q_UNUSED(t) - if (d.type() == Device::Type::LVM_Device) { + if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device) { return 0; } diff --git a/src/jobs/createpartitiontablejob.cpp b/src/jobs/createpartitiontablejob.cpp index 557a5e4..f67cae9 100644 --- a/src/jobs/createpartitiontablejob.cpp +++ b/src/jobs/createpartitiontablejob.cpp @@ -44,7 +44,7 @@ bool CreatePartitionTableJob::run(Report& parent) Report* report = jobStarted(parent); - if (device().type() == Device::Type::Disk_Device) { + if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice != nullptr) { diff --git a/src/jobs/setpartgeometryjob.cpp b/src/jobs/setpartgeometryjob.cpp index 30e218a..b1c9d6f 100644 --- a/src/jobs/setpartgeometryjob.cpp +++ b/src/jobs/setpartgeometryjob.cpp @@ -55,7 +55,7 @@ bool SetPartGeometryJob::run(Report& parent) Report* report = jobStarted(parent); - if(device().type() == Device::Type::Disk_Device) { + if(device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { From e2f88dbbf9f3e6cbc700847fc9ed807094672b20 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Wed, 11 Jul 2018 12:03:44 -0300 Subject: [PATCH 132/175] Including SoftwareRAID attributes getters. --- src/core/raid/softwareraid.cpp | 30 ++++++++++++++++++++++++++++++ src/core/raid/softwareraid.h | 7 +++++++ 2 files changed, 37 insertions(+) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 883947e..fb8de56 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -89,6 +89,36 @@ bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) return false; } +qint32 SoftwareRAID::raidLevel() const +{ + return d_ptr->m_raidLevel; +} + +qint64 SoftwareRAID::chunkSize() const +{ + return d_ptr->m_chunkSize; +} + +qint64 SoftwareRAID::totalChunk() const +{ + return d_ptr->m_totalChunk; +} + +qint64 SoftwareRAID::arraySize() const +{ + return d_ptr->m_arraySize; +} + +QString SoftwareRAID::uuid() const +{ + return d_ptr->m_UUID; +} + +QStringList SoftwareRAID::devicePathList() const +{ + return d_ptr->m_devicePathList; +} + void SoftwareRAID::scanSoftwareRAID(QList& devices) { ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index 641350f..edafb10 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -37,6 +37,13 @@ public: virtual bool shrinkArray(Report& report, const QStringList& devices); + qint32 raidLevel() const; + qint64 chunkSize() const; + qint64 totalChunk() const; + qint64 arraySize() const; + QString uuid() const; + QStringList devicePathList() const; + public: static void scanSoftwareRAID(QList& devices); From d51404c7f1b262331329ca1a1e97e3f9bd9dea4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 11 Jul 2018 23:36:20 +0100 Subject: [PATCH 133/175] sfdisk: fix returned partition name This makes it work with partitions such as /dev/mmcblk1p2 --- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index c169a8c..5faf5c8 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -76,12 +76,16 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p if ( createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) + type + QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { - QRegularExpression re(QStringLiteral("Created a new partition (\\d)")); + QRegularExpression re(QStringLiteral("Created a new partition (\\d+)")); QRegularExpressionMatch rem = re.match(createCommand.output()); - // TODO: Needs refactoring. Workaround to check if device path is RAID and include 'p' character before partition number. - if (rem.hasMatch()) - return partition.devicePath() + (SoftwareRAID::isRaidPath(partition.devicePath()) ? QStringLiteral("p") : QStringLiteral("")) + rem.captured(1); + if (rem.hasMatch()) { + // TODO: Use back() with Qt 5.10 + if ( partition.devicePath()[partition.devicePath().size() - 1].isDigit() ) + return partition.devicePath() + QLatin1Char('p') + rem.captured(1); + else + return partition.devicePath() + rem.captured(1); + } } report.line() << xi18nc("@info:progress", "Failed to add partition %1 to device %2.", partition.deviceNode(), m_device->deviceNode()); From b11b73b1e59f548b9e2a4ee636e6812bf34d5bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Thu, 12 Jul 2018 00:12:43 +0100 Subject: [PATCH 134/175] Remove extra semicolon after Q_UNUSED. --- src/core/raid/softwareraid.cpp | 26 +++++++++++++------------- src/fs/exfat.cpp | 4 ++-- src/fs/linuxswap.cpp | 6 +++--- src/fs/ntfs.cpp | 2 +- src/fs/ocfs2.cpp | 2 +- src/plugins/dummy/dummydevice.cpp | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index fb8de56..8dfd604 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -71,21 +71,21 @@ const QStringList& SoftwareRAID::partitionNodes() const qint64 SoftwareRAID::partitionSize(QString &partitionPath) const { - Q_UNUSED(partitionPath); + Q_UNUSED(partitionPath) return 0; } bool SoftwareRAID::growArray(Report &report, const QStringList &devices) { - Q_UNUSED(report); - Q_UNUSED(devices); + Q_UNUSED(report) + Q_UNUSED(devices) return false; } bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) { - Q_UNUSED(report); - Q_UNUSED(devices); + Q_UNUSED(report) + Q_UNUSED(devices) return false; } @@ -186,13 +186,13 @@ qint64 SoftwareRAID::getArraySize(const QString &path) QString SoftwareRAID::getUUID(const QString &path) { - Q_UNUSED(path); + Q_UNUSED(path) return QStringLiteral(); } QStringList SoftwareRAID::getDevicePathList(const QString &path) { - Q_UNUSED(path); + Q_UNUSED(path) return {}; } @@ -213,22 +213,22 @@ bool SoftwareRAID::createSoftwareRAID(Report &report, bool SoftwareRAID::deleteSoftwareRAID(Report &report, SoftwareRAID &raidDevice) { - Q_UNUSED(report); - Q_UNUSED(raidDevice); + Q_UNUSED(report) + Q_UNUSED(raidDevice) return false; } bool SoftwareRAID::assembleSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) { - Q_UNUSED(report); - Q_UNUSED(raidDevice); + Q_UNUSED(report) + Q_UNUSED(raidDevice) return false; } bool SoftwareRAID::stopSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) { - Q_UNUSED(report); - Q_UNUSED(raidDevice); + Q_UNUSED(report) + Q_UNUSED(raidDevice) return false; } diff --git a/src/fs/exfat.cpp b/src/fs/exfat.cpp index 1971a63..3173450 100644 --- a/src/fs/exfat.cpp +++ b/src/fs/exfat.cpp @@ -112,8 +112,8 @@ bool exfat::writeLabel(Report& report, const QString& deviceNode, const QString& bool exfat::updateUUID(Report& report, const QString& deviceNode) const { - Q_UNUSED(report); - Q_UNUSED(deviceNode); + Q_UNUSED(report) + Q_UNUSED(deviceNode) return false; } diff --git a/src/fs/linuxswap.cpp b/src/fs/linuxswap.cpp index b4eebdd..e535d67 100644 --- a/src/fs/linuxswap.cpp +++ b/src/fs/linuxswap.cpp @@ -89,7 +89,7 @@ bool linuxswap::create(Report& report, const QString& deviceNode) bool linuxswap::resize(Report& report, const QString& deviceNode, qint64 length) const { - Q_UNUSED(length); + Q_UNUSED(length) const QString label = readLabel(deviceNode); const QString uuid = readUUID(deviceNode); @@ -145,14 +145,14 @@ QString linuxswap::unmountTitle() const } bool linuxswap::canMount(const QString& deviceNode, const QString& mountPoint) const { - Q_UNUSED(deviceNode); + Q_UNUSED(deviceNode) // linux swap doesn't require mount point to activate return mountPoint != QStringLiteral("/"); } bool linuxswap::mount(Report& report, const QString& deviceNode, const QString& mountPoint) { - Q_UNUSED(mountPoint); + Q_UNUSED(mountPoint) ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index 8386275..043d5de 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -170,7 +170,7 @@ bool ntfs::resize(Report& report, const QString& deviceNode, qint64 length) cons bool ntfs::updateUUID(Report& report, const QString& deviceNode) const { - Q_UNUSED(report); + Q_UNUSED(report) ExternalCommand cmd(QStringLiteral("ntfslabel"), { QStringLiteral("--new-serial"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; diff --git a/src/fs/ocfs2.cpp b/src/fs/ocfs2.cpp index 1122e64..8f2e914 100644 --- a/src/fs/ocfs2.cpp +++ b/src/fs/ocfs2.cpp @@ -99,7 +99,7 @@ qint64 ocfs2::maxCapacity() const qint64 ocfs2::readUsedCapacity(const QString& deviceNode) const { - Q_UNUSED(deviceNode); + Q_UNUSED(deviceNode) return -1; } diff --git a/src/plugins/dummy/dummydevice.cpp b/src/plugins/dummy/dummydevice.cpp index 0ffa283..26634a7 100644 --- a/src/plugins/dummy/dummydevice.cpp +++ b/src/plugins/dummy/dummydevice.cpp @@ -54,8 +54,8 @@ std::unique_ptr DummyDevice::openPartitionTable() bool DummyDevice::createPartitionTable(Report& report, const PartitionTable& ptable) { - Q_UNUSED(report); - Q_UNUSED(ptable); + Q_UNUSED(report) + Q_UNUSED(ptable) return true; } From 3f7c5ca7228cf2c65e5d535e80cd1fb930a98b04 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Thu, 12 Jul 2018 14:08:24 -0300 Subject: [PATCH 135/175] Reassemble Software RAID when commit partition table. --- src/core/raid/softwareraid.cpp | 18 ++++++++++-------- src/core/raid/softwareraid.h | 6 ++---- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 7 +++++++ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 8dfd604..3fc6938 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -218,18 +218,20 @@ bool SoftwareRAID::deleteSoftwareRAID(Report &report, return false; } -bool SoftwareRAID::assembleSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) +bool SoftwareRAID::assembleSoftwareRAID(const SoftwareRAID &raidDevice) { - Q_UNUSED(report) - Q_UNUSED(raidDevice) - return false; + ExternalCommand cmd(QStringLiteral("mdadm"), + { QStringLiteral("--assemble"), QStringLiteral("--scan"), raidDevice.deviceNode() }); + + return cmd.run(-1) && cmd.exitCode() == 0; } -bool SoftwareRAID::stopSoftwareRAID(Report &report, const SoftwareRAID &raidDevice) +bool SoftwareRAID::stopSoftwareRAID(const SoftwareRAID &raidDevice) { - Q_UNUSED(report) - Q_UNUSED(raidDevice) - return false; + ExternalCommand cmd(QStringLiteral("mdadm"), + { QStringLiteral("--stop"), raidDevice.deviceNode() }); + + return cmd.run(-1) && cmd.exitCode() == 0; } void SoftwareRAID::initPartitions() diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index edafb10..6145388 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -65,11 +65,9 @@ public: static bool deleteSoftwareRAID(Report& report, SoftwareRAID& raidDevice); - static bool assembleSoftwareRAID(Report& report, - const SoftwareRAID& raidDevice); + static bool assembleSoftwareRAID(const SoftwareRAID& raidDevice); - static bool stopSoftwareRAID(Report& report, - const SoftwareRAID& raidDevice); + static bool stopSoftwareRAID(const SoftwareRAID& raidDevice); protected: void initPartitions() override; diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 5faf5c8..c794d01 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -57,6 +57,13 @@ bool SfdiskPartitionTable::commit(quint32 timeout) ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run(); ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("trigger") }).run(); + if (m_device->type() == Device::Type::SoftwareRAID_Device) + { + const SoftwareRAID& raid = static_cast(*m_device); + SoftwareRAID::stopSoftwareRAID(raid); + SoftwareRAID::assembleSoftwareRAID(raid); + } + return true; } From d8602817f082c82b89948e53c7e834b64cf5935c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Thu, 12 Jul 2018 14:38:52 -0300 Subject: [PATCH 136/175] Adding reassemble method for SoftwareRAID. --- src/core/raid/softwareraid.cpp | 19 +++++++++++++++---- src/core/raid/softwareraid.h | 6 ++++-- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 7 +------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 3fc6938..4f81fe2 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -218,22 +218,33 @@ bool SoftwareRAID::deleteSoftwareRAID(Report &report, return false; } -bool SoftwareRAID::assembleSoftwareRAID(const SoftwareRAID &raidDevice) +bool SoftwareRAID::assembleSoftwareRAID(const QString& deviceNode) { + if (!isRaidPath(deviceNode)) + return false; + ExternalCommand cmd(QStringLiteral("mdadm"), - { QStringLiteral("--assemble"), QStringLiteral("--scan"), raidDevice.deviceNode() }); + { QStringLiteral("--assemble"), QStringLiteral("--scan"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } -bool SoftwareRAID::stopSoftwareRAID(const SoftwareRAID &raidDevice) +bool SoftwareRAID::stopSoftwareRAID(const QString& deviceNode) { + if (!isRaidPath(deviceNode)) + return false; + ExternalCommand cmd(QStringLiteral("mdadm"), - { QStringLiteral("--stop"), raidDevice.deviceNode() }); + { QStringLiteral("--stop"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } +bool SoftwareRAID::reassembleSoftwareRAID(const QString &deviceNode) +{ + return stopSoftwareRAID(deviceNode) && assembleSoftwareRAID(deviceNode); +} + void SoftwareRAID::initPartitions() { diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index 6145388..580bf84 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -65,9 +65,11 @@ public: static bool deleteSoftwareRAID(Report& report, SoftwareRAID& raidDevice); - static bool assembleSoftwareRAID(const SoftwareRAID& raidDevice); + static bool assembleSoftwareRAID(const QString& deviceNode); - static bool stopSoftwareRAID(const SoftwareRAID& raidDevice); + static bool stopSoftwareRAID(const QString& deviceNode); + + static bool reassembleSoftwareRAID(const QString& deviceNode); protected: void initPartitions() override; diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index c794d01..a6637d1 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -57,12 +57,7 @@ bool SfdiskPartitionTable::commit(quint32 timeout) ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run(); ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("trigger") }).run(); - if (m_device->type() == Device::Type::SoftwareRAID_Device) - { - const SoftwareRAID& raid = static_cast(*m_device); - SoftwareRAID::stopSoftwareRAID(raid); - SoftwareRAID::assembleSoftwareRAID(raid); - } + SoftwareRAID::reassembleSoftwareRAID(m_device->deviceNode()); return true; } From b3e0dbe15ab92547e3d653329dfc5f83632adc2c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 13 Jul 2018 16:20:38 -0300 Subject: [PATCH 137/175] Adding full command option for detail and stop Software RAID. --- src/core/raid/softwareraid.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 4f81fe2..7f0449d 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -121,6 +121,7 @@ QStringList SoftwareRAID::devicePathList() const void SoftwareRAID::scanSoftwareRAID(QList& devices) { + // TODO: Check configuration file and load all the devices that aren't in /proc/mdstat as innactive ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { @@ -235,7 +236,7 @@ bool SoftwareRAID::stopSoftwareRAID(const QString& deviceNode) return false; ExternalCommand cmd(QStringLiteral("mdadm"), - { QStringLiteral("--stop"), deviceNode }); + { QStringLiteral("--manage"), QStringLiteral("--stop"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } @@ -258,7 +259,6 @@ qint64 SoftwareRAID::mappedSector(const QString &partitionPath, qint64 sector) c QString SoftwareRAID::getDetail(const QString &path) { ExternalCommand cmd(QStringLiteral("mdadm"), - { QStringLiteral("--detail"), - path }); + { QStringLiteral("--misc"), QStringLiteral("--detail"), path }); return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QStringLiteral(); } From 6803d6bc670cdb3fbf556b5e9abab63a98bd82a7 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 13 Jul 2018 17:56:13 -0300 Subject: [PATCH 138/175] Including RAID level in SoftwareRAID device pretty name. --- src/core/raid/softwareraid.cpp | 6 ++++++ src/core/raid/softwareraid.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 7f0449d..2da301e 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -25,6 +25,7 @@ #include "fs/filesystemfactory.h" #include "util/externalcommand.h" +#include #include #define d_ptr std::static_pointer_cast(d) @@ -89,6 +90,11 @@ bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) return false; } +QString SoftwareRAID::prettyName() const +{ + return VolumeManagerDevice::prettyName() + xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()); +} + qint32 SoftwareRAID::raidLevel() const { return d_ptr->m_raidLevel; diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index 580bf84..0951d37 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -37,6 +37,8 @@ public: virtual bool shrinkArray(Report& report, const QStringList& devices); + virtual QString prettyName() const override; + qint32 raidLevel() const; qint64 chunkSize() const; qint64 totalChunk() const; From aa23ecdc3c0ec996f0b1c623cca629211639abf3 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 13 Jul 2018 19:33:08 -0300 Subject: [PATCH 139/175] Software RAID devices can be created containing '/' character after 'md'. (e.g. /dev/md/alpha0) --- src/core/raid/softwareraid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 2da301e..cb22899 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -131,7 +131,7 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { - QRegularExpression re(QStringLiteral("md(\\d+)\\s+:")); + QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:")); QRegularExpressionMatchIterator i = re.globalMatch(scanRaid.output()); while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); From 252b1086606e57626a75544dda557e960ba79b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 14 Jul 2018 13:11:18 +0100 Subject: [PATCH 140/175] Abort LVM scanning when lvdisplay command fails. --- src/core/lvmdevice.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 90cf852..7842777 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -18,15 +18,16 @@ #include "core/lvmdevice.h" #include "core/partition.h" +#include "core/partitiontable.h" #include "core/volumemanagerdevice_p.h" #include "fs/filesystem.h" #include "fs/lvm2_pv.h" #include "fs/luks.h" #include "fs/filesystemfactory.h" -#include "core/partitiontable.h" #include "util/externalcommand.h" #include "util/helpers.h" +#include "util/globallog.h" #include "util/report.h" #include @@ -97,19 +98,34 @@ void LvmDevice::initPartitions() pTable->append(p); } - pTable->updateUnallocated(*this); + if (!pTable) + pTable->updateUnallocated(*this); + else + pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable); setPartitionTable(pTable); } /** + * Scan LVM LV Partitions + * + * This deletes pTable when LVM scanning error is encountered + * + * @param pTable Virtual PartitionTable of LVM device * @return an initialized Partition(LV) list */ const QList LvmDevice::scanPartitions(PartitionTable* pTable) const { QList pList; for (const auto &lvPath : partitionNodes()) { - pList.append(scanPartition(lvPath, pTable)); + Partition *p = scanPartition(lvPath, pTable); + if (p) + pList.append(p); + else { + pList.clear(); + delete pTable; + break; + } } return pList; } @@ -133,6 +149,9 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl activateLV(lvPath); qint64 lvSize = getTotalLE(lvPath); + if (lvSize == -1) + return nullptr; + qint64 startSector = mappedSector(lvPath, 0); qint64 endSector = startSector + lvSize - 1; @@ -350,6 +369,7 @@ qint64 LvmDevice::getTotalLE(const QString& lvPath) return match.captured(1).toInt(); } } + Log(Log::Level::error) << xi18nc("@info:status", "An error occurred while running lvdisplay."); return -1; } From 65ef6ab83d364442fa679affea249a56718b197a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 14 Jul 2018 21:36:13 +0100 Subject: [PATCH 141/175] Fix error message. It was incorrectly saying DBus session bus instead of system bus. --- src/util/externalcommandhelper.cpp | 2 +- src/util/globallog.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index e1527d4..123e300 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -32,7 +32,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) { ActionReply reply; if (!QDBusConnection::systemBus().isConnected()) { - qWarning() << "Could not connect to DBus session bus"; + qWarning() << "Could not connect to DBus system bus"; reply.addData(QStringLiteral("success"), false); return reply; } diff --git a/src/util/globallog.h b/src/util/globallog.h index 3c1bdaf..3cb57fd 100644 --- a/src/util/globallog.h +++ b/src/util/globallog.h @@ -15,8 +15,7 @@ * along with this program. If not, see .* *************************************************************************/ -#if !defined(KPMCORE_GLOBALLOG_H) - +#ifndef KPMCORE_GLOBALLOG_H #define KPMCORE_GLOBALLOG_H #include "util/libpartitionmanagerexport.h" From 51780a62975b7b14baceda091ca0e9e267846b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 00:09:39 +0100 Subject: [PATCH 142/175] Stop KAuth helper if application crashes. This is implemented by pinging application from KAuth helper via DBus. If it is busy then KAuth helper also waits for the current job to finish. --- src/util/CMakeLists.txt | 1 + src/util/externalcommand.cpp | 28 +++++++++++- src/util/externalcommand.h | 13 +++++- src/util/externalcommandhelper.cpp | 43 +++++++++++++++++-- .../org.kde.kpmcore.applicationinterface.conf | 14 ++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 src/util/org.kde.kpmcore.applicationinterface.conf diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 6e3abb2..4d1fd5a 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -34,6 +34,7 @@ target_link_libraries(kpmcore_externalcommand install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d ) +install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d ) kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root) kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index a165913..716e43b 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -22,10 +22,12 @@ #include "core/copytarget.h" #include "core/copysourcedevice.h" #include "core/copytargetdevice.h" +#include "util/globallog.h" #include "util/externalcommand.h" #include "util/report.h" #include +#include #include #include #include @@ -51,6 +53,7 @@ struct ExternalCommandPrivate int m_ExitCode; QByteArray m_Output; QByteArray m_Input; + DBusThread *m_thread; }; unsigned int ExternalCommand::counter = 0; @@ -75,7 +78,8 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co d->m_Output = QByteArray(); if (!helperStarted) - startHelper(); + if(!startHelper()) + Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges."); setup(processChannelMode); } @@ -346,6 +350,13 @@ void ExternalCommand::setExitCode(int i) bool ExternalCommand::startHelper() { + if (!QDBusConnection::systemBus().isConnected()) { + qWarning() << "Could not connect to DBus session bus"; + return false; + } + d->m_thread = new DBusThread; + d->m_thread->start(); + init = new QCA::Initializer; // Generate RSA key pair for signing external command requests if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) { @@ -402,3 +413,18 @@ void ExternalCommand::stopHelper() delete privateKey; delete init; } + +void DBusThread::run() +{ + if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface"))) { + qWarning() << QDBusConnection::systemBus().lastError().message(); + return; + } + if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) { + qWarning() << QDBusConnection::systemBus().lastError().message(); + return; + } + + QEventLoop loop; + loop.exec(); +} diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index b260b10..069640b 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,16 @@ class CopySource; class CopyTarget; struct ExternalCommandPrivate; +class DBusThread : public QThread +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.ping") + void run() override; + +public Q_SLOTS: + Q_SCRIPTABLE void ping() {return;}; +}; + /** An external command. Runs an external command as a child process. @@ -94,7 +105,7 @@ public: // KAuth /**< start ExternalCommand Helper */ - static bool startHelper(); + bool startHelper(); /**< stop ExternalCommand Helper */ static void stopHelper(); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 123e300..61f0212 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -27,6 +27,18 @@ #include /** Initialize ExternalCommandHelper Daemon and prepare DBus interface + * + * KAuth helper runs in the background until application exits. + * To avoid forever running helper in case of application crash + * ExternalCommand class opens DBus interface that we ping. + * If helper is not busy than it exits when ping fails. Otherwise, + * we wait for the current job to finish before exiting, so even in case + * of main application crash, we do not leave partially moved data. + * + * This helper also starts another DBus interface where it listens to + * command execution requests from the application that started the helper. + * These requests are validated using public key cryptography, to prevent + * other unprivileged applications from gaining root privileges. */ ActionReply ExternalCommandHelper::init(const QVariantMap& args) { @@ -36,17 +48,42 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) reply.addData(QStringLiteral("success"), false); return reply; } - m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); - m_Counter = 0; if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) { qWarning() << QDBusConnection::systemBus().lastError().message(); reply.addData(QStringLiteral("success"), false); return reply; } - QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots); + if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots)) { + qWarning() << QDBusConnection::systemBus().lastError().message(); + reply.addData(QStringLiteral("success"), false); + return reply; + } + + m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); + m_Counter = 0; HelperSupport::progressStep(QVariantMap()); + auto timeout = [this] () { + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.applicationinterface"), + QStringLiteral("/Application"), + QStringLiteral("org.kde.kpmcore.ping"), + QDBusConnection::systemBus()); + iface.setTimeout(5000); // 5 seconds; + auto pcall = iface.asyncCall(QStringLiteral("ping")); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { + if (watcher->isError()) { + qWarning() << watcher->error(); + m_loop.exit(); + } + }; + connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); + }; + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, timeout); + timer->start(5000); // 5 seconds m_loop.exec(); reply.addData(QStringLiteral("success"), true); diff --git a/src/util/org.kde.kpmcore.applicationinterface.conf b/src/util/org.kde.kpmcore.applicationinterface.conf new file mode 100644 index 0000000..59113ff --- /dev/null +++ b/src/util/org.kde.kpmcore.applicationinterface.conf @@ -0,0 +1,14 @@ + + + + + + + + + + + From f572681684ba0bf02ffeaf5408ccdd550b55a248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 00:28:38 +0100 Subject: [PATCH 143/175] Partially revert 252b1086606e57626a75544dda557e960ba79b53. That commit broke LVM support. --- src/core/lvmdevice.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 7842777..96957be 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -90,18 +90,18 @@ LvmDevice::~LvmDevice() void LvmDevice::initPartitions() { qint64 firstUsable = 0; - qint64 lastusable = totalPE() - 1; - PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable); + qint64 lastUsable = totalPE() - 1; + PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastUsable); for (const auto &p : scanPartitions(pTable)) { LVSizeMap()->insert(p->partitionPath(), p->length()); pTable->append(p); } - if (!pTable) + if (pTable) pTable->updateUnallocated(*this); else - pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable); + pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastUsable); setPartitionTable(pTable); } @@ -109,8 +109,6 @@ void LvmDevice::initPartitions() /** * Scan LVM LV Partitions * - * This deletes pTable when LVM scanning error is encountered - * * @param pTable Virtual PartitionTable of LVM device * @return an initialized Partition(LV) list */ @@ -119,13 +117,7 @@ const QList LvmDevice::scanPartitions(PartitionTable* pTable) const QList pList; for (const auto &lvPath : partitionNodes()) { Partition *p = scanPartition(lvPath, pTable); - if (p) - pList.append(p); - else { - pList.clear(); - delete pTable; - break; - } + pList.append(p); } return pList; } @@ -149,9 +141,6 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl activateLV(lvPath); qint64 lvSize = getTotalLE(lvPath); - if (lvSize == -1) - return nullptr; - qint64 startSector = mappedSector(lvPath, 0); qint64 endSector = startSector + lvSize - 1; From 9a8166fe6568599c5f922c21dc5a927516ebe18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 00:35:55 +0100 Subject: [PATCH 144/175] Remove qDebug message. It shouldn't be necessary now. Helper exits reliably. --- src/util/externalcommandhelper.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 61f0212..29b3918 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -288,10 +288,8 @@ void ExternalCommandHelper::exit(const QByteArray& signature) m_loop.exit(); - if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"))) - qDebug() << "org.kde.kpmcore.helperinterface unregistered"; - QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper")); + QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface")); } void ExternalCommandHelper::onReadOutput() From ce425ee04de9be2cc5bbcce6c6594eb5ddb72c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 01:13:54 +0100 Subject: [PATCH 145/175] Exit if the previous KAuth helper is still running. --- src/util/externalcommand.cpp | 5 +++++ src/util/externalcommandhelper.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 716e43b..0f4a629 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -354,6 +354,11 @@ bool ExternalCommand::startHelper() qWarning() << "Could not connect to DBus session bus"; return false; } + QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); + if (iface.isValid()) { + exit(0); + } + d->m_thread = new DBusThread; d->m_thread->start(); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 29b3918..a1d2b87 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -69,7 +69,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) QStringLiteral("/Application"), QStringLiteral("org.kde.kpmcore.ping"), QDBusConnection::systemBus()); - iface.setTimeout(5000); // 5 seconds; + iface.setTimeout(2000); // 2 seconds; auto pcall = iface.asyncCall(QStringLiteral("ping")); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { From fde4ac62a064e73a886d6da522efcdf5e0355d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 12:02:39 +0100 Subject: [PATCH 146/175] Bump version number. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30f1eb6..b1a8e9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) set(QT_MIN_VERSION "5.7.0") set(VERSION_MAJOR "3") -set(VERSION_MINOR "3") +set(VERSION_MINOR "50") set(VERSION_RELEASE "0") set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}) set(SOVERSION "8") From 5828e9daac3e0a381890585aa25819779c158a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 13:03:07 +0100 Subject: [PATCH 147/175] Scan LVM devices after RAID. This should allow us to find LVM PVs that are on RAID devices. --- src/plugins/sfdisk/sfdiskbackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index fed674e..09431ce 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -106,8 +106,8 @@ QList SfdiskBackend::scanDevices(bool excludeReadOnly) } } - LvmDevice::scanSystemLVM(result); SoftwareRAID::scanSoftwareRAID(result); + LvmDevice::scanSystemLVM(result); // LVM scanner needs all other devices, so should be last } return result; From a0b9a93b6b437455e73cebac5b7d480714d7db95 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 10:31:27 -0300 Subject: [PATCH 148/175] Support inactive RAID devices. --- src/core/raid/softwareraid.cpp | 120 ++++++++++++++++++++-- src/core/raid/softwareraid.h | 9 +- src/ops/createpartitiontableoperation.cpp | 14 ++- 3 files changed, 131 insertions(+), 12 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index cb22899..6cb0eaa 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -39,9 +39,10 @@ public: qint64 m_arraySize; QString m_UUID; QStringList m_devicePathList; + bool m_active; }; -SoftwareRAID::SoftwareRAID(const QString& name, const QString& iconName) +SoftwareRAID::SoftwareRAID(const QString& name, bool active, const QString& iconName) : VolumeManagerDevice(std::make_shared(), name, (QStringLiteral("/dev/") + name), @@ -56,6 +57,7 @@ SoftwareRAID::SoftwareRAID(const QString& name, const QString& iconName) d_ptr->m_arraySize = getArraySize(deviceNode()); d_ptr->m_UUID = getUUID(deviceNode()); d_ptr->m_devicePathList = getDevicePathList(deviceNode()); + d_ptr->m_active = active; initPartitions(); } @@ -92,7 +94,23 @@ bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) QString SoftwareRAID::prettyName() const { - return VolumeManagerDevice::prettyName() + xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()); + return VolumeManagerDevice::prettyName() + + (isActive() ? xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()) : + QStringLiteral(" [RAID]")); +} + +bool SoftwareRAID::operator ==(const Device& other) const +{ + bool equalDeviceNode = Device::operator ==(other); + + if (other.type() == Device::Type::SoftwareRAID_Device) { + const SoftwareRAID& raid = static_cast(other); + + if (!equalDeviceNode) + return raid.uuid() == uuid(); + } + + return equalDeviceNode; } qint32 SoftwareRAID::raidLevel() const @@ -125,9 +143,37 @@ QStringList SoftwareRAID::devicePathList() const return d_ptr->m_devicePathList; } +bool SoftwareRAID::isActive() const +{ + return d_ptr->m_active; +} + +void SoftwareRAID::setActive(bool active) +{ + d_ptr->m_active = active; +} + void SoftwareRAID::scanSoftwareRAID(QList& devices) { - // TODO: Check configuration file and load all the devices that aren't in /proc/mdstat as innactive + QList scannedRaid; + + // TODO: Support custom config files. + QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf")); + + if (!config.isEmpty()) { + QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/([\\/\\w-]+)")); + QRegularExpressionMatchIterator i = re.globalMatch(config); + + while (i.hasNext()) { + QRegularExpressionMatch reMatch = i.next(); + QString deviceName = reMatch.captured(1).trimmed(); + + SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, false); + + scannedRaid << raidDevice; + } + } + ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { @@ -136,14 +182,18 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); - QString deviceNode = QStringLiteral("/dev/") + QStringLiteral("md") + reMatch.captured(1).trimmed(); + QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed(); - Device* d = CoreBackendManager::self()->backend()->scanDevice(deviceNode); + SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); - if ( d ) - devices << d; + if (scannedRaid.contains(d)) + d->setActive(true); + else + scannedRaid << d; } } + + devices << scannedRaid; } qint32 SoftwareRAID::getRaidLevel(const QString &path) @@ -193,8 +243,51 @@ qint64 SoftwareRAID::getArraySize(const QString &path) QString SoftwareRAID::getUUID(const QString &path) { - Q_UNUSED(path) - return QStringLiteral(); + QString output = getDetail(path); + + if (!output.isEmpty()) { + QRegularExpression re(QStringLiteral("UUID :\\s+([\\w:]+)")); + QRegularExpressionMatch reMatch = re.match(output); + + if (reMatch.hasMatch()) + return reMatch.captured(1); + } + + // If UUID was not found in detail output, it should be searched in config file + + // TODO: Support custom config files. + QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf")); + + if (!config.isEmpty()) { + QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/md([\\/\\w-]+)(.*)")); + QRegularExpressionMatchIterator i = re.globalMatch(config); + + while (i.hasNext()) { + QRegularExpressionMatch reMatch = i.next(); + QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed(); + QString otherInfo = reMatch.captured(2).trimmed(); + + // Consider device node as name=host:deviceNode when the captured device node string has '-' character + // It happens when user have included the device to config file using 'mdadm --examine --scan' + if (deviceNode.contains(QLatin1Char('-'))) { + QRegularExpression reName(QStringLiteral("name=[\\w:]+\\/dev\\/md\\/([\\/\\w]+)")); + QRegularExpressionMatch nameMatch = reName.match(otherInfo); + + if (nameMatch.hasMatch()) + deviceNode = nameMatch.captured(1); + } + + if (deviceNode == path) { + QRegularExpression reUUID(QStringLiteral("(UUID=|uuid=)([\\w:]+)")); + QRegularExpressionMatch uuidMatch = reUUID.match(otherInfo); + + if (uuidMatch.hasMatch()) + return uuidMatch.captured(2); + } + } + } + + return QString(); } QStringList SoftwareRAID::getDevicePathList(const QString &path) @@ -266,5 +359,12 @@ QString SoftwareRAID::getDetail(const QString &path) { ExternalCommand cmd(QStringLiteral("mdadm"), { QStringLiteral("--misc"), QStringLiteral("--detail"), path }); - return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QStringLiteral(); + return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString(); +} + +QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath) +{ + ExternalCommand cmd(QStringLiteral("cat"), { configurationPath }); + + return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString(); } diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index 0951d37..6fd56ee 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -27,7 +27,7 @@ class LIBKPMCORE_EXPORT SoftwareRAID : public VolumeManagerDevice Q_DISABLE_COPY(SoftwareRAID) public: - SoftwareRAID(const QString& name, const QString& iconName = QString()); + SoftwareRAID(const QString& name, bool active = true, const QString& iconName = QString()); const QStringList deviceNodes() const override; const QStringList& partitionNodes() const override; @@ -39,12 +39,17 @@ public: virtual QString prettyName() const override; + virtual bool operator==(const Device& other) const override; + qint32 raidLevel() const; qint64 chunkSize() const; qint64 totalChunk() const; qint64 arraySize() const; QString uuid() const; QStringList devicePathList() const; + bool isActive() const; + + void setActive(bool active); public: static void scanSoftwareRAID(QList& devices); @@ -80,6 +85,8 @@ protected: private: static QString getDetail(const QString& path); + + static QString getRAIDConfiguration(const QString& configurationPath); }; #endif // SOFTWARERAID_H diff --git a/src/ops/createpartitiontableoperation.cpp b/src/ops/createpartitiontableoperation.cpp index f3ed270..57b5738 100644 --- a/src/ops/createpartitiontableoperation.cpp +++ b/src/ops/createpartitiontableoperation.cpp @@ -21,6 +21,7 @@ #include "core/device.h" #include "core/partitiontable.h" #include "core/partition.h" +#include "core/raid/softwareraid.h" #include "jobs/createpartitiontablejob.h" @@ -93,7 +94,18 @@ bool CreatePartitionTableOperation::execute(Report& parent) */ bool CreatePartitionTableOperation::canCreate(const Device* device) { - return (device != nullptr) && (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted()) && (device->type() != Device::Type::LVM_Device); + if (device == nullptr) + return false; + + if (device->type() == Device::Type::SoftwareRAID_Device) { + const SoftwareRAID* raid = static_cast(device); + + if (!raid->isActive()) + return false; + } + + return (device->partitionTable() == nullptr || !device->partitionTable()->isChildMounted()) + && (device->type() != Device::Type::LVM_Device); } QString CreatePartitionTableOperation::description() const From dff99ffcf54ff7e41e6a1bd51c94a9c4c99bcb74 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 12:06:54 -0300 Subject: [PATCH 149/175] Support RAID devices which are in resync/recovery process after its creation/assemble. Revert modelCommand.output().trimmed().isEmpty() check in SfdiskBackend::scanDevice. --- src/core/raid/softwareraid.cpp | 25 +++++++++++++++++-------- src/plugins/sfdisk/sfdiskbackend.cpp | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 6cb0eaa..3caf39e 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -161,12 +161,12 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf")); if (!config.isEmpty()) { - QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/([\\/\\w-]+)")); + QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/([\\/\\w-]+)")); QRegularExpressionMatchIterator i = re.globalMatch(config); while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); - QString deviceName = reMatch.captured(1).trimmed(); + QString deviceName = reMatch.captured(2).trimmed(); SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, false); @@ -177,17 +177,26 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { - QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:")); + QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:\\s+([\\w]+)")); QRegularExpressionMatchIterator i = re.globalMatch(scanRaid.output()); while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed(); + QString status = reMatch.captured(2).trimmed(); SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); - if (scannedRaid.contains(d)) - d->setActive(true); + if (scannedRaid.contains(d)) { + d->setActive(status.toLower() == QStringLiteral("active")); + + QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); + + QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); + + if (reMirrorStatusMatch.hasMatch()) + d->setActive(false); + } else scannedRaid << d; } @@ -259,13 +268,13 @@ QString SoftwareRAID::getUUID(const QString &path) QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf")); if (!config.isEmpty()) { - QRegularExpression re(QStringLiteral("[\\t\\r\\n\\f\\s]ARRAY \\/dev\\/md([\\/\\w-]+)(.*)")); + QRegularExpression re(QStringLiteral("([\\t\\r\\n\\f\\s]|INACTIVE-)ARRAY \\/dev\\/md([\\/\\w-]+)(.*)")); QRegularExpressionMatchIterator i = re.globalMatch(config); while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); - QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(1).trimmed(); - QString otherInfo = reMatch.captured(2).trimmed(); + QString deviceNode = QStringLiteral("/dev/md") + reMatch.captured(2).trimmed(); + QString otherInfo = reMatch.captured(3).trimmed(); // Consider device node as name=host:deviceNode when the captured device node string has '-' character // It happens when user have included the device to config file using 'mdadm --examine --scan' diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 09431ce..bd454b9 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -136,7 +136,7 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); int logicalSectorSize = sizeCommand2.output().trimmed().toLongLong(); - if ( modelCommand.run(-1) && modelCommand.exitCode() == 0 && !modelCommand.output().trimmed().isEmpty() ) + if ( modelCommand.run(-1) && modelCommand.exitCode() == 0 ) { QString modelName = modelCommand.output(); modelName = modelName.left(modelName.length() - 1); From fae6cd4d6189a93b7d3a3681c845851df485306c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 12:10:19 -0300 Subject: [PATCH 150/175] RAID 0 devices don't need to check for resync/recovery progress. --- src/core/raid/softwareraid.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 3caf39e..4baf1d8 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -190,12 +190,14 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) if (scannedRaid.contains(d)) { d->setActive(status.toLower() == QStringLiteral("active")); - QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); + if (d->raidLevel() > 0) { + QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); - QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); + QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); - if (reMirrorStatusMatch.hasMatch()) - d->setActive(false); + if (reMirrorStatusMatch.hasMatch()) + d->setActive(false); + } } else scannedRaid << d; From f3fac7eac7d856eb519085a951a27bd019cd0466 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 13:11:50 -0300 Subject: [PATCH 151/175] Add SoftwareRAID::Status enum. Check for RAID before modelCommand in SfdiskBackend::scanDevice. --- src/core/raid/softwareraid.cpp | 53 ++++++++++++++--------- src/core/raid/softwareraid.h | 15 +++++-- src/ops/createpartitiontableoperation.cpp | 2 +- src/plugins/sfdisk/sfdiskbackend.cpp | 26 +++++------ 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 4baf1d8..e30fd02 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -39,10 +39,10 @@ public: qint64 m_arraySize; QString m_UUID; QStringList m_devicePathList; - bool m_active; + SoftwareRAID::Status m_status; }; -SoftwareRAID::SoftwareRAID(const QString& name, bool active, const QString& iconName) +SoftwareRAID::SoftwareRAID(const QString& name, SoftwareRAID::Status status, const QString& iconName) : VolumeManagerDevice(std::make_shared(), name, (QStringLiteral("/dev/") + name), @@ -57,7 +57,7 @@ SoftwareRAID::SoftwareRAID(const QString& name, bool active, const QString& icon d_ptr->m_arraySize = getArraySize(deviceNode()); d_ptr->m_UUID = getUUID(deviceNode()); d_ptr->m_devicePathList = getDevicePathList(deviceNode()); - d_ptr->m_active = active; + d_ptr->m_status = status; initPartitions(); } @@ -94,9 +94,14 @@ bool SoftwareRAID::shrinkArray(Report &report, const QStringList &devices) QString SoftwareRAID::prettyName() const { - return VolumeManagerDevice::prettyName() + - (isActive() ? xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()) : - QStringLiteral(" [RAID]")); + QString raidInfo; + + if (status() != SoftwareRAID::Status::Inactive) + raidInfo = xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()); + else + raidInfo = QStringLiteral(" [RAID]"); + + return VolumeManagerDevice::prettyName() + raidInfo; } bool SoftwareRAID::operator ==(const Device& other) const @@ -143,14 +148,14 @@ QStringList SoftwareRAID::devicePathList() const return d_ptr->m_devicePathList; } -bool SoftwareRAID::isActive() const +SoftwareRAID::Status SoftwareRAID::status() const { - return d_ptr->m_active; + return d_ptr->m_status; } -void SoftwareRAID::setActive(bool active) +void SoftwareRAID::setStatus(SoftwareRAID::Status status) { - d_ptr->m_active = active; + d_ptr->m_status = status; } void SoftwareRAID::scanSoftwareRAID(QList& devices) @@ -168,7 +173,8 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) QRegularExpressionMatch reMatch = i.next(); QString deviceName = reMatch.captured(2).trimmed(); - SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, false); + SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, + SoftwareRAID::Status::Inactive); scannedRaid << raidDevice; } @@ -188,19 +194,24 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); if (scannedRaid.contains(d)) { - d->setActive(status.toLower() == QStringLiteral("active")); - - if (d->raidLevel() > 0) { - QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); - - QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); - - if (reMirrorStatusMatch.hasMatch()) - d->setActive(false); - } + if (status == QStringLiteral("inactive")) + d->setStatus(SoftwareRAID::Status::Inactive); } else scannedRaid << d; + + if (d->raidLevel() > 0) { + QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); + + QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); + + if (reMirrorStatusMatch.hasMatch()) { + if (reMirrorStatusMatch.captured(1) == QStringLiteral("resync")) + d->setStatus(SoftwareRAID::Status::Resync); + else if (reMirrorStatusMatch.captured(1) == QStringLiteral("recovery")) + d->setStatus(SoftwareRAID::Status::Recovery); + } + } } } diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index 6fd56ee..a33c5d3 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -27,7 +27,16 @@ class LIBKPMCORE_EXPORT SoftwareRAID : public VolumeManagerDevice Q_DISABLE_COPY(SoftwareRAID) public: - SoftwareRAID(const QString& name, bool active = true, const QString& iconName = QString()); + enum class Status { + Active, + Inactive, + Resync, + Recovery, + }; + + SoftwareRAID(const QString& name, + SoftwareRAID::Status status = SoftwareRAID::Status::Active, + const QString& iconName = QString()); const QStringList deviceNodes() const override; const QStringList& partitionNodes() const override; @@ -47,9 +56,9 @@ public: qint64 arraySize() const; QString uuid() const; QStringList devicePathList() const; - bool isActive() const; + SoftwareRAID::Status status() const; - void setActive(bool active); + void setStatus(SoftwareRAID::Status status); public: static void scanSoftwareRAID(QList& devices); diff --git a/src/ops/createpartitiontableoperation.cpp b/src/ops/createpartitiontableoperation.cpp index 57b5738..f68b122 100644 --- a/src/ops/createpartitiontableoperation.cpp +++ b/src/ops/createpartitiontableoperation.cpp @@ -100,7 +100,7 @@ bool CreatePartitionTableOperation::canCreate(const Device* device) if (device->type() == Device::Type::SoftwareRAID_Device) { const SoftwareRAID* raid = static_cast(device); - if (!raid->isActive()) + if (raid->status() == SoftwareRAID::Status::Inactive) return false; } diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index bd454b9..de78602 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -136,7 +136,18 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); int logicalSectorSize = sizeCommand2.output().trimmed().toLongLong(); - if ( modelCommand.run(-1) && modelCommand.exitCode() == 0 ) + ExternalCommand softwareRaidCommand(QStringLiteral("mdadm"), { QStringLiteral("--detail"), deviceNode }); + + if ( softwareRaidCommand.run(-1) && softwareRaidCommand.exitCode() == 0 ) + { + Log(Log::Level::information) << xi18nc("@info:status", "Software RAID Device found: %1", deviceNode); + + QString deviceName = deviceNode.mid(5); + + d = new SoftwareRAID( deviceName, SoftwareRAID::Status::Active ); + } + + if ( d == nullptr && modelCommand.run(-1) && modelCommand.exitCode() == 0 ) { QString modelName = modelCommand.output(); modelName = modelName.left(modelName.length() - 1); @@ -145,19 +156,6 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) d = new DiskDevice(modelName, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); } - else // check for software raid - { - ExternalCommand softwareRaidCommand(QStringLiteral("mdadm"), { QStringLiteral("--detail"), deviceNode }); - - if ( softwareRaidCommand.run(-1) && softwareRaidCommand.exitCode() == 0 ) - { - Log(Log::Level::information) << xi18nc("@info:status", "Software RAID Device found: %1", deviceNode); - - QString deviceName = deviceNode.mid(5); - - d = new SoftwareRAID( deviceName ); - } - } if ( d ) { From e761c131d03f1dd3d942c6abe923dcdfff0cbb75 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 13:21:12 -0300 Subject: [PATCH 152/175] Changing prettyName for RAID devices with Resync/Recovery status. --- src/core/raid/softwareraid.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index e30fd02..5273106 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -96,8 +96,12 @@ QString SoftwareRAID::prettyName() const { QString raidInfo; - if (status() != SoftwareRAID::Status::Inactive) + if (status() == SoftwareRAID::Status::Active) raidInfo = xi18nc("@item:inlistbox [RAID level]", " [RAID %1]", raidLevel()); + else if (status() == SoftwareRAID::Status::Recovery) + raidInfo = xi18nc("@item:inlistbox [RAID level - Recovering]", " [RAID %1 - Recovering]", raidLevel()); + else if (status() == SoftwareRAID::Status::Resync) + raidInfo = xi18nc("@item:inlistbox [RAID level - Resyncing]", " [RAID %1 - Resyncing]", raidLevel()); else raidInfo = QStringLiteral(" [RAID]"); @@ -193,13 +197,12 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); - if (scannedRaid.contains(d)) { - if (status == QStringLiteral("inactive")) - d->setStatus(SoftwareRAID::Status::Inactive); - } - else + if (!scannedRaid.contains(d)) scannedRaid << d; + if (status == QStringLiteral("inactive")) + d->setStatus(SoftwareRAID::Status::Inactive); + if (d->raidLevel() > 0) { QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); From e5b63b0d6f9df45d9463c73444f9050256f5bb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 17:37:15 +0100 Subject: [PATCH 153/175] Fix support for QProcess::ProcessChannelMode. --- src/util/externalcommand.cpp | 17 +++++++++-------- src/util/externalcommand.h | 1 - src/util/externalcommandhelper.cpp | 4 +++- src/util/externalcommandhelper.h | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 0f4a629..2514294 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -54,6 +54,7 @@ struct ExternalCommandPrivate QByteArray m_Output; QByteArray m_Input; DBusThread *m_thread; + QProcess::ProcessChannelMode processChannelMode; }; unsigned int ExternalCommand::counter = 0; @@ -81,7 +82,7 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co if(!startHelper()) Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges."); - setup(processChannelMode); + d->processChannelMode = processChannelMode; } /** Creates a new ExternalCommand instance with Report. @@ -98,20 +99,18 @@ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStri d->m_ExitCode = -1; d->m_Output = QByteArray(); - setup(processChannelMode); + d->processChannelMode = processChannelMode; } ExternalCommand::~ExternalCommand() { } -void ExternalCommand::setup(const QProcess::ProcessChannelMode processChannelMode) -{ -// d->arguments.insert(QStringLiteral("processChannelMode"), processChannelMode); // FIXME - +// void ExternalCommand::setup() +// { // connect(this, qOverload(&QProcess::finished), this, &ExternalCommand::onFinished); // connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); -} +// } /** Executes the external command. @param timeout timeout to wait for the process to start @@ -150,6 +149,7 @@ bool ExternalCommand::start(int timeout) for (const auto &argument : qAsConst(d->m_Args)) request.append(argument.toUtf8()); request.append(d->m_Input); + request.append(d->processChannelMode); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); @@ -157,7 +157,8 @@ bool ExternalCommand::start(int timeout) privateKey->signMessage(hash, QCA::EMSA3_Raw), cmd, args(), - d->m_Input); + d->m_Input, + d->processChannelMode); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 069640b..9f24c9f 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -126,7 +126,6 @@ public Q_SLOTS: private: void setExitCode(int i); - void setup(const QProcess::ProcessChannelMode processChannelMode); void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index a1d2b87..e12cccc 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -244,7 +244,7 @@ bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QStrin return rval; } -QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input) +QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) { QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QVariantMap reply; @@ -255,6 +255,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr for (const auto &argument : arguments) request.append(argument.toUtf8()); request.append(input); + request.append(processChannelMode); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { qCritical() << xi18n("Invalid cryptographic signature"); @@ -265,6 +266,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr // connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput); m_cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } ); + m_cmd.setProcessChannelMode(static_cast(processChannelMode)); m_cmd.start(command, arguments); m_cmd.write(input); m_cmd.closeWriteChannel(); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 818c76c..60453ef 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -43,7 +43,7 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); - Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input); + Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QByteArray& signature); From cacc6f6067a36aeee4208ce61e80774e08da7b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 15 Jul 2018 17:56:30 +0100 Subject: [PATCH 154/175] Require cmake 3.1. Older version do not support CMAKE_CXX_STANDARD. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1a8e9d..1d751e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ project(kpmcore) -cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(CMAKE_USE_RELATIVE_PATHS OFF) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) From a508cfbc834bd8355594a9fcc407782005edc29e Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 15:51:23 -0300 Subject: [PATCH 155/175] Avoiding pointer comparison. --- src/core/raid/softwareraid.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 5273106..b919479 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -164,7 +164,7 @@ void SoftwareRAID::setStatus(SoftwareRAID::Status status) void SoftwareRAID::scanSoftwareRAID(QList& devices) { - QList scannedRaid; + QStringList availableInConf; // TODO: Support custom config files. QString config = getRAIDConfiguration(QStringLiteral("/etc/mdadm.conf")); @@ -177,10 +177,7 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) QRegularExpressionMatch reMatch = i.next(); QString deviceName = reMatch.captured(2).trimmed(); - SoftwareRAID *raidDevice = new SoftwareRAID(deviceName, - SoftwareRAID::Status::Inactive); - - scannedRaid << raidDevice; + availableInConf << deviceName; } } @@ -197,8 +194,18 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); - if (!scannedRaid.contains(d)) - scannedRaid << d; + bool isInConf = false; + + for (const QString& path : qAsConst(availableInConf)) { + if (getUUID(QStringLiteral("/dev/") + path) == d->uuid()) { + isInConf = true; + availableInConf.removeAll(path); + break; + } + } + + if (isInConf) + devices << d; if (status == QStringLiteral("inactive")) d->setStatus(SoftwareRAID::Status::Inactive); @@ -218,7 +225,10 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) } } - devices << scannedRaid; + for (const QString& name : qAsConst(availableInConf)) { + SoftwareRAID *raidDevice = new SoftwareRAID(name, SoftwareRAID::Status::Inactive); + devices << raidDevice; + } } qint32 SoftwareRAID::getRaidLevel(const QString &path) From 3fd221f7941dc6fd7f6c66e5a73c28bc36fb50fa Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 16:36:43 -0300 Subject: [PATCH 156/175] Ranged-for in availableInConf const copy. All the scanned devices should be added to devices list. --- src/core/raid/softwareraid.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index b919479..c7c9c42 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -194,18 +194,13 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); - bool isInConf = false; + const QStringList constAvailableInConf = availableInConf; - for (const QString& path : qAsConst(availableInConf)) { - if (getUUID(QStringLiteral("/dev/") + path) == d->uuid()) { - isInConf = true; + for (const QString& path : constAvailableInConf) + if (getUUID(QStringLiteral("/dev/") + path) == d->uuid()) availableInConf.removeAll(path); - break; - } - } - if (isInConf) - devices << d; + devices << d; if (status == QStringLiteral("inactive")) d->setStatus(SoftwareRAID::Status::Inactive); From 2298d08c41b27fcec7b1ba888d87af9e59d7278c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 17:38:43 -0300 Subject: [PATCH 157/175] Adding support for detecting linux_raid_member file system. --- src/fs/CMakeLists.txt | 2 + src/fs/filesystem.cpp | 6 ++- src/fs/filesystem.h | 1 + src/fs/filesystemfactory.cpp | 63 +++++++++++++++------------- src/fs/linuxraidmember.cpp | 28 +++++++++++++ src/fs/linuxraidmember.h | 41 ++++++++++++++++++ src/plugins/sfdisk/sfdiskbackend.cpp | 1 + 7 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 src/fs/linuxraidmember.cpp create mode 100644 src/fs/linuxraidmember.h diff --git a/src/fs/CMakeLists.txt b/src/fs/CMakeLists.txt index b7ead6a..93661a6 100644 --- a/src/fs/CMakeLists.txt +++ b/src/fs/CMakeLists.txt @@ -16,6 +16,7 @@ set(FS_SRC fs/hpfs.cpp fs/iso9660.cpp fs/jfs.cpp + fs/linuxraidmember.cpp fs/linuxswap.cpp fs/luks.cpp fs/luks2.cpp @@ -51,6 +52,7 @@ set(FS_LIB_HDRS fs/hpfs.h fs/iso9660.h fs/jfs.h + fs/linuxraidmember.h fs/linuxswap.h fs/luks.h fs/luks2.h diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index bac502c..8de5ee4 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -68,7 +68,8 @@ const std::vector FileSystem::defaultColorCode = QColor( 170,120,255 ), // udf QColor( 177,82,69 ), // iso9660 QColor( 223,39,104 ), // luks2 - QColor( 204,179,255 ) // fat12 + QColor( 204,179,255 ), // fat12 + QColor( 255,100,100 ) // linux_raid_member } }; @@ -445,7 +446,8 @@ static const KLocalizedString* typeNames() kxi18nc("@item filesystem name", "udf"), kxi18nc("@item filesystem name", "iso9660"), kxi18nc("@item filesystem name", "luks2"), - kxi18nc("@item filesystem name", "fat12") + kxi18nc("@item filesystem name", "fat12"), + kxi18nc("@item filesystem name", "linux_raid_member"), }; return s; diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 110107a..a411b24 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -91,6 +91,7 @@ public: Iso9660, Luks2, Fat12, + LinuxRaidMember, __lastType }; diff --git a/src/fs/filesystemfactory.cpp b/src/fs/filesystemfactory.cpp index fa6b120..6f99054 100644 --- a/src/fs/filesystemfactory.cpp +++ b/src/fs/filesystemfactory.cpp @@ -34,6 +34,7 @@ #include "fs/hpfs.h" #include "fs/iso9660.h" #include "fs/jfs.h" +#include "fs/linuxraidmember.h" #include "fs/linuxswap.h" #include "fs/luks.h" #include "fs/luks2.h" @@ -76,6 +77,7 @@ void FileSystemFactory::init() m_FileSystems.insert(FileSystem::Type::Hpfs, new FS::hpfs(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Iso9660, new FS::iso9660(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Jfs, new FS::jfs(-1, -1, -1, QString())); + m_FileSystems.insert(FileSystem::Type::LinuxRaidMember, new FS::linuxraidmember(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::LinuxSwap, new FS::linuxswap(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Luks, new FS::luks(-1, -1, -1, QString())); m_FileSystems.insert(FileSystem::Type::Luks2, new FS::luks2(-1, -1, -1, QString())); @@ -111,36 +113,37 @@ FileSystem* FileSystemFactory::create(FileSystem::Type t, qint64 firstsector, qi FileSystem* fs = nullptr; switch (t) { - case FileSystem::Type::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break; - case FileSystem::Type::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Btrfs: fs = new FS::btrfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Exfat: fs = new FS::exfat(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext2: fs = new FS::ext2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext3: fs = new FS::ext3(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ext4: fs = new FS::ext4(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Extended: fs = new FS::extended(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::F2fs: fs = new FS::f2fs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat12: fs = new FS::fat12(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat16: fs = new FS::fat16(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Fat32: fs = new FS::fat32(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Hfs: fs = new FS::hfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::HfsPlus: fs = new FS::hfsplus(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Hpfs: fs = new FS::hpfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Iso9660: fs = new FS::iso9660(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Jfs: fs = new FS::jfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::LinuxRaidMember: fs = new FS::linuxraidmember(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::LinuxSwap: fs = new FS::linuxswap(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Luks: fs = new FS::luks(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Luks2: fs = new FS::luks2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Lvm2_PV: fs = new FS::lvm2_pv(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Nilfs2: fs = new FS::nilfs2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ntfs: fs = new FS::ntfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ocfs2: fs = new FS::ocfs2(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::ReiserFS: fs = new FS::reiserfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Reiser4: fs = new FS::reiser4(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Udf: fs = new FS::udf(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Ufs: fs = new FS::ufs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Unformatted: fs = new FS::unformatted(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Unknown: fs = new FS::unknown(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Xfs: fs = new FS::xfs(firstsector, lastsector, sectorsused, label); break; + case FileSystem::Type::Zfs: fs = new FS::zfs(firstsector, lastsector, sectorsused, label); break; default: break; } diff --git a/src/fs/linuxraidmember.cpp b/src/fs/linuxraidmember.cpp new file mode 100644 index 0000000..19b4825 --- /dev/null +++ b/src/fs/linuxraidmember.cpp @@ -0,0 +1,28 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#include "fs/linuxraidmember.h" + +namespace FS +{ + +linuxraidmember::linuxraidmember(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label) : + FileSystem(firstsector, lastsector, sectorsused, label, FileSystem::Type::LinuxRaidMember) +{ +} + +} diff --git a/src/fs/linuxraidmember.h b/src/fs/linuxraidmember.h new file mode 100644 index 0000000..aa71cdd --- /dev/null +++ b/src/fs/linuxraidmember.h @@ -0,0 +1,41 @@ +/************************************************************************* + * Copyright (C) 2018 by Caio Carvalho * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 3 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see .* + *************************************************************************/ + +#ifndef LINUXRAIDMEMBER_H +#define LINUXRAIDMEMBER_H + +#include "util/libpartitionmanagerexport.h" + +#include "fs/filesystem.h" + +class Report; + +class QString; + +namespace FS +{ +/** A linux_raid_member file system. + @author Caio Carvalho + */ +class LIBKPMCORE_EXPORT linuxraidmember : public FileSystem +{ +public: + linuxraidmember(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label); +}; +} + +#endif // LINUXRAIDMEMBER_H diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index de78602..9630b1c 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -415,6 +415,7 @@ FileSystem::Type SfdiskBackend::detectFileSystem(const QString& partitionPath) else if (s == QStringLiteral("f2fs")) rval = FileSystem::Type::F2fs; else if (s == QStringLiteral("udf")) rval = FileSystem::Type::Udf; else if (s == QStringLiteral("iso9660")) rval = FileSystem::Type::Iso9660; + else if (s == QStringLiteral("linux_raid_member")) rval = FileSystem::Type::LinuxRaidMember; else qWarning() << "unknown file system type " << s << " on " << partitionPath; } From c1e393240bd85332200cb162f5b764f409f2f4c9 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 19:38:33 -0300 Subject: [PATCH 158/175] Using QFile instead of calling ExternalCommand to read /proc/mdstat and mdadm.conf files. --- src/core/raid/softwareraid.cpp | 66 ++++++++++++++++++++++++---- src/core/raid/softwareraid.h | 2 + src/plugins/sfdisk/sfdiskbackend.cpp | 30 ++++++++++--- 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index c7c9c42..83d0039 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -26,6 +26,7 @@ #include "util/externalcommand.h" #include +#include #include #define d_ptr std::static_pointer_cast(d) @@ -181,11 +182,17 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) } } - ExternalCommand scanRaid(QStringLiteral("cat"), { QStringLiteral("/proc/mdstat") }); + QFile mdstat(QStringLiteral("/proc/mdstat")); + + if (mdstat.open(QIODevice::ReadOnly)) { + QTextStream stream(&mdstat); + + QString content = stream.readAll(); + + mdstat.close(); - if (scanRaid.run(-1) && scanRaid.exitCode() == 0) { QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:\\s+([\\w]+)")); - QRegularExpressionMatchIterator i = re.globalMatch(scanRaid.output()); + QRegularExpressionMatchIterator i = re.globalMatch(content); while (i.hasNext()) { QRegularExpressionMatch reMatch = i.next(); @@ -194,6 +201,10 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) SoftwareRAID* d = static_cast(CoreBackendManager::self()->backend()->scanDevice(deviceNode)); + // Just to prevent segfault in some case + if (d == nullptr) + continue; + const QStringList constAvailableInConf = availableInConf; for (const QString& path : constAvailableInConf) @@ -206,14 +217,14 @@ void SoftwareRAID::scanSoftwareRAID(QList& devices) d->setStatus(SoftwareRAID::Status::Inactive); if (d->raidLevel() > 0) { - QRegularExpression reMirrorStatus(QStringLiteral("\\[[=>.]+\\]\\s+(resync|recovery)")); + QRegularExpression reMirrorStatus(d->name() + QStringLiteral("\\s+:\\s+(.*\\n\\s+)+\\[[=>.]+\\]\\s+(resync|recovery)")); - QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(scanRaid.output()); + QRegularExpressionMatch reMirrorStatusMatch = reMirrorStatus.match(content); if (reMirrorStatusMatch.hasMatch()) { - if (reMirrorStatusMatch.captured(1) == QStringLiteral("resync")) + if (reMirrorStatusMatch.captured(2) == QStringLiteral("resync")) d->setStatus(SoftwareRAID::Status::Resync); - else if (reMirrorStatusMatch.captured(1) == QStringLiteral("recovery")) + else if (reMirrorStatusMatch.captured(2) == QStringLiteral("recovery")) d->setStatus(SoftwareRAID::Status::Recovery); } } @@ -375,6 +386,34 @@ bool SoftwareRAID::reassembleSoftwareRAID(const QString &deviceNode) return stopSoftwareRAID(deviceNode) && assembleSoftwareRAID(deviceNode); } +bool SoftwareRAID::isRaidMember(const QString &path) +{ + QFile mdstat(QStringLiteral("/proc/mdstat")); + + if (!mdstat.open(QIODevice::ReadOnly)) + return false; + + QTextStream stream(&mdstat); + + QString content = stream.readAll(); + + mdstat.close(); + + QRegularExpression re(QStringLiteral("(\\w+)\\[\\d+\\]")); + QRegularExpressionMatchIterator i = re.globalMatch(content); + + while (i.hasNext()) { + QRegularExpressionMatch reMatch = i.next(); + + QString match = QStringLiteral("/dev/") + reMatch.captured(1); + + if (match == path) + return true; + } + + return false; +} + void SoftwareRAID::initPartitions() { @@ -394,7 +433,16 @@ QString SoftwareRAID::getDetail(const QString &path) QString SoftwareRAID::getRAIDConfiguration(const QString &configurationPath) { - ExternalCommand cmd(QStringLiteral("cat"), { configurationPath }); + QFile config(configurationPath); - return (cmd.run(-1) && cmd.exitCode() == 0) ? cmd.output() : QString(); + if (!config.open(QIODevice::ReadOnly)) + return QString(); + + QTextStream stream(&config); + + QString result = stream.readAll(); + + config.close(); + + return result; } diff --git a/src/core/raid/softwareraid.h b/src/core/raid/softwareraid.h index a33c5d3..803ec54 100644 --- a/src/core/raid/softwareraid.h +++ b/src/core/raid/softwareraid.h @@ -87,6 +87,8 @@ public: static bool reassembleSoftwareRAID(const QString& deviceNode); + static bool isRaidMember(const QString& path); + protected: void initPartitions() override; diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 9630b1c..d8a5f36 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -136,15 +136,33 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); int logicalSectorSize = sizeCommand2.output().trimmed().toLongLong(); - ExternalCommand softwareRaidCommand(QStringLiteral("mdadm"), { QStringLiteral("--detail"), deviceNode }); + QFile mdstat(QStringLiteral("/proc/mdstat")); - if ( softwareRaidCommand.run(-1) && softwareRaidCommand.exitCode() == 0 ) - { - Log(Log::Level::information) << xi18nc("@info:status", "Software RAID Device found: %1", deviceNode); + if (mdstat.open(QIODevice::ReadOnly)) { + QTextStream stream(&mdstat); - QString deviceName = deviceNode.mid(5); + QString content = stream.readAll(); - d = new SoftwareRAID( deviceName, SoftwareRAID::Status::Active ); + mdstat.close(); + + QRegularExpression re(QStringLiteral("md([\\/\\w]+)\\s+:")); + QRegularExpressionMatchIterator i = re.globalMatch(content); + + while (i.hasNext()) { + + QRegularExpressionMatch reMatch = i.next(); + + QString name = reMatch.captured(1); + + if ((QStringLiteral("/dev/md") + name) == deviceNode) { + Log(Log::Level::information) << xi18nc("@info:status", "Software RAID Device found: %1", deviceNode); + + d = new SoftwareRAID( QStringLiteral("md") + name, SoftwareRAID::Status::Active ); + + break; + } + + } } if ( d == nullptr && modelCommand.run(-1) && modelCommand.exitCode() == 0 ) From 9138e02726ae9906a64198af0f7f693b8508d3d0 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Sun, 15 Jul 2018 19:41:44 -0300 Subject: [PATCH 159/175] Operations should check LvmDevice::s_DirtyPVs instead of check pending CreateVolumeGroupOperations to search for newly LVM PVs. --- src/ops/deleteoperation.cpp | 27 +++++++++++++++------------ src/ops/deleteoperation.h | 2 +- src/ops/resizeoperation.cpp | 30 ++++++++++++------------------ src/ops/resizeoperation.h | 8 ++++---- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/ops/deleteoperation.cpp b/src/ops/deleteoperation.cpp index 0a83c96..d1ec00c 100644 --- a/src/ops/deleteoperation.cpp +++ b/src/ops/deleteoperation.cpp @@ -16,12 +16,13 @@ * along with this program. If not, see .* *************************************************************************/ -#include "ops/createvolumegroupoperation.h" #include "ops/deleteoperation.h" #include "core/partition.h" #include "core/device.h" +#include "core/lvmdevice.h" #include "core/partitiontable.h" +#include "core/raid/softwareraid.h" #include "fs/luks.h" #include "jobs/deletepartitionjob.h" @@ -111,7 +112,7 @@ void DeleteOperation::checkAdjustLogicalNumbers(Partition& p, bool undo) @param p the Partition in question, may be nullptr. @return true if @p p can be deleted. */ -bool DeleteOperation::canDelete(const Partition* p, const QList pendingOps) +bool DeleteOperation::canDelete(const Partition* p) { if (p == nullptr) return false; @@ -120,11 +121,12 @@ bool DeleteOperation::canDelete(const Partition* p, const QList pen return false; if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } + if (LvmDevice::s_DirtyPVs.contains(p)) + return false; + } + else if (p->fileSystem().type() == FileSystem::Type::LinuxRaidMember) { + if (SoftwareRAID::isRaidMember(p->partitionPath())) + return false; } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM @@ -132,11 +134,12 @@ bool DeleteOperation::canDelete(const Partition* p, const QList pen if (fs) { if (fs->type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return false; - } + if (LvmDevice::s_DirtyPVs.contains(p)) + return false; + } + else if (fs->type() == FileSystem::Type::LinuxRaidMember) { + if (SoftwareRAID::isRaidMember(p->partitionPath())) + return false; } } } diff --git a/src/ops/deleteoperation.h b/src/ops/deleteoperation.h index 39faccd..682abd2 100644 --- a/src/ops/deleteoperation.h +++ b/src/ops/deleteoperation.h @@ -68,7 +68,7 @@ public: bool targets(const Device& d) const override; bool targets(const Partition& p) const override; - static bool canDelete(const Partition* p, const QList pendingOps = QList()); + static bool canDelete(const Partition* p); protected: Device& targetDevice() { diff --git a/src/ops/resizeoperation.cpp b/src/ops/resizeoperation.cpp index d73df26..249f2b1 100644 --- a/src/ops/resizeoperation.cpp +++ b/src/ops/resizeoperation.cpp @@ -20,6 +20,7 @@ #include "core/partition.h" #include "core/device.h" +#include "core/lvmdevice.h" #include "core/partitiontable.h" #include "core/copysourcedevice.h" #include "core/copytargetdevice.h" @@ -30,7 +31,6 @@ #include "jobs/movefilesystemjob.h" #include "ops/checkoperation.h" -#include "ops/createvolumegroupoperation.h" #include "fs/filesystem.h" #include "fs/luks.h" @@ -329,12 +329,12 @@ bool ResizeOperation::grow(Report& report) @param p the Partition in question, may be nullptr. @return true if @p p can be grown. */ -bool ResizeOperation::canGrow(const Partition* p, const QList pendingOps) +bool ResizeOperation::canGrow(const Partition* p) { if (p == nullptr) return false; - if (isLVMPVinNewlyVG(p, pendingOps)) + if (isLVMPVinNewlyVG(p)) return false; // we can always grow, shrink or move a partition not yet written to disk @@ -351,12 +351,12 @@ bool ResizeOperation::canGrow(const Partition* p, const QList pendi @param p the Partition in question, may be nullptr. @return true if @p p can be shrunk. */ -bool ResizeOperation::canShrink(const Partition* p, const QList pendingOps) +bool ResizeOperation::canShrink(const Partition* p) { if (p == nullptr) return false; - if (isLVMPVinNewlyVG(p, pendingOps)) + if (isLVMPVinNewlyVG(p)) return false; // we can always grow, shrink or move a partition not yet written to disk @@ -376,12 +376,12 @@ bool ResizeOperation::canShrink(const Partition* p, const QList pen @param p the Partition in question, may be nullptr. @return true if @p p can be moved. */ -bool ResizeOperation::canMove(const Partition* p, const QList pendingOps) +bool ResizeOperation::canMove(const Partition* p) { if (p == nullptr) return false; - if (isLVMPVinNewlyVG(p, pendingOps)) + if (isLVMPVinNewlyVG(p)) return false; // we can always grow, shrink or move a partition not yet written to disk @@ -399,14 +399,11 @@ bool ResizeOperation::canMove(const Partition* p, const QList pendi return p->fileSystem().supportMove() != FileSystem::cmdSupportNone; } -bool ResizeOperation::isLVMPVinNewlyVG(const Partition *p, const QList pendingOps) +bool ResizeOperation::isLVMPVinNewlyVG(const Partition *p) { if (p->fileSystem().type() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return true; - } + if (LvmDevice::s_DirtyPVs.contains(p)) + return true; } else if (p->fileSystem().type() == FileSystem::Type::Luks || p->fileSystem().type() == FileSystem::Type::Luks2) { // See if innerFS is LVM @@ -414,11 +411,8 @@ bool ResizeOperation::isLVMPVinNewlyVG(const Partition *p, const QListtype() == FileSystem::Type::Lvm2_PV) { - // See if there is a newly created VG targeting this partition - for (Operation *op : qAsConst(pendingOps)) { - if (dynamic_cast(op) && op->targets(*p)) - return true; - } + if (LvmDevice::s_DirtyPVs.contains(p)) + return true; } } } diff --git a/src/ops/resizeoperation.h b/src/ops/resizeoperation.h index 975d08f..c8bf148 100644 --- a/src/ops/resizeoperation.h +++ b/src/ops/resizeoperation.h @@ -85,9 +85,9 @@ public: bool targets(const Device& d) const override; bool targets(const Partition& p) const override; - static bool canGrow(const Partition* p, const QList pendingOps = QList()); - static bool canShrink(const Partition* p, const QList pendingOps = QList()); - static bool canMove(const Partition* p, const QList pendingOps = QList()); + static bool canGrow(const Partition* p); + static bool canShrink(const Partition* p); + static bool canMove(const Partition* p); protected: Device& targetDevice() { @@ -159,7 +159,7 @@ protected: } private: - static bool isLVMPVinNewlyVG(const Partition* p, const QList pendingOps); + static bool isLVMPVinNewlyVG(const Partition* p); private: Device& m_TargetDevice; From 64419caa8d85e883bdd2c4efdfc5e44582a0111e Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 16 Jul 2018 15:39:47 -0300 Subject: [PATCH 160/175] Add chunk size for RAID 1 arrays. --- src/core/raid/softwareraid.cpp | 48 ++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/core/raid/softwareraid.cpp b/src/core/raid/softwareraid.cpp index 83d0039..21aebd9 100644 --- a/src/core/raid/softwareraid.cpp +++ b/src/core/raid/softwareraid.cpp @@ -253,12 +253,28 @@ qint32 SoftwareRAID::getRaidLevel(const QString &path) qint64 SoftwareRAID::getChunkSize(const QString &path) { - QString output = getDetail(path); - if (!output.isEmpty()) { - QRegularExpression re(QStringLiteral("Chunk Size :\\s+(\\d+)")); - QRegularExpressionMatch reMatch = re.match(output); - if (reMatch.hasMatch()) - return reMatch.captured(1).toLongLong(); + if (getRaidLevel(path) == 1) { + QStringList devices = getDevicePathList(path); + + if (!devices.isEmpty()) { + QString device = devices[0]; + // Look sector size for the first device/partition on the list, as RAID 1 is composed by mirrored devices + ExternalCommand sectorSize(QStringLiteral("blockdev"), { QStringLiteral("--getss"), device }); + + if (sectorSize.run(-1) && sectorSize.exitCode() == 0) { + int sectors = sectorSize.output().trimmed().toLongLong(); + return sectors; + } + } + } + else { + QString output = getDetail(path); + if (!output.isEmpty()) { + QRegularExpression re(QStringLiteral("Chunk Size :\\s+(\\d+)")); + QRegularExpressionMatch reMatch = re.match(output); + if (reMatch.hasMatch()) + return reMatch.captured(1).toLongLong(); + } } return -1; @@ -333,8 +349,24 @@ QString SoftwareRAID::getUUID(const QString &path) QStringList SoftwareRAID::getDevicePathList(const QString &path) { - Q_UNUSED(path) - return {}; + QStringList result; + + QString detail = getDetail(path); + + if (!detail.isEmpty()) { + QRegularExpression re(QStringLiteral("\\s+\\/dev\\/(\\w+)")); + QRegularExpressionMatchIterator i = re.globalMatch(detail); + + while (i.hasNext()) { + QRegularExpressionMatch match = i.next(); + + QString device = QStringLiteral("/dev/") + match.captured(1); + if (device != path) + result << device; + } + } + + return result; } bool SoftwareRAID::isRaidPath(const QString &path) From 3f65e9465914f300aebc8fe3832626d8f0aa9f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 18 Jul 2018 21:40:39 +0100 Subject: [PATCH 161/175] Return false when external command helper reports failure. --- src/util/externalcommand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 2514294..f96cf74 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -174,7 +174,7 @@ bool ExternalCommand::start(int timeout) d->m_Output = reply.value()[QStringLiteral("output")].toByteArray(); setExitCode(reply.value()[QStringLiteral("exitCode")].toInt()); - rval = true; + rval = reply.value()[QStringLiteral("success")].toBool(); } }; From 8a9b5589eaf285e0c34f746938509e38a64a0182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 18 Jul 2018 21:53:48 +0100 Subject: [PATCH 162/175] Bump minimum Qt version to 5.10. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d751e1..3c1f456 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(CMAKE_USE_RELATIVE_PATHS OFF) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) -set(QT_MIN_VERSION "5.7.0") +set(QT_MIN_VERSION "5.10.0") set(VERSION_MAJOR "3") set(VERSION_MINOR "50") set(VERSION_RELEASE "0") From 985b3531463f815c4bfc98cc1c10cc810d6b3d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Wed, 18 Jul 2018 23:23:34 +0100 Subject: [PATCH 163/175] Use QString::back(). --- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index a6637d1..ebaeedd 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -82,8 +82,7 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p QRegularExpressionMatch rem = re.match(createCommand.output()); if (rem.hasMatch()) { - // TODO: Use back() with Qt 5.10 - if ( partition.devicePath()[partition.devicePath().size() - 1].isDigit() ) + if ( partition.devicePath().back().isDigit() ) return partition.devicePath() + QLatin1Char('p') + rem.captured(1); else return partition.devicePath() + rem.captured(1); From 48761e0e2b8b815824b54fce10758843ce77e808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 20 Jul 2018 19:04:32 +0100 Subject: [PATCH 164/175] ecm_configure_package_config_file -> configure_package_config_file. --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c1f456..ae7c043 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,6 @@ include(KDECompilerSettings NO_POLICY_SCOPE) include(FeatureSummary) include(GenerateExportHeader) include(ECMSetupVersion) -include(ECMPackageConfigHelpers) ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h" @@ -92,7 +91,7 @@ add_subdirectory(src) set(INCLUDE_INSTALL_DIR "include/kpmcore/") set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KPMcore") -ecm_configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KPMcoreConfig.cmake.in" +configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KPMcoreConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KPMcoreConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} PATH_VARS INCLUDE_INSTALL_DIR From c50e04c9d1581635c5a518cda08c1734155e0748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Fri, 20 Jul 2018 21:12:13 +0100 Subject: [PATCH 165/175] Use cryptographic nonce instead of counters. --- src/plugins/sfdisk/sfdiskbackend.cpp | 1 - src/util/externalcommand.cpp | 30 ++++++++++++++++++++++++---- src/util/externalcommand.h | 4 +++- src/util/externalcommandhelper.cpp | 18 +++++++++++++---- src/util/externalcommandhelper.h | 5 ++++- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index d8a5f36..357c6db 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -196,7 +196,6 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) if (checkVG.run(-1) && checkVG.exitCode() == 0) { - qDebug() << "Trying to find LVM VG"; QList availableDevices = scanDevices(); LvmDevice::scanSystemLVM(availableDevices); diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index f96cf74..a1030c0 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -57,7 +57,6 @@ struct ExternalCommandPrivate QProcess::ProcessChannelMode processChannelMode; }; -unsigned int ExternalCommand::counter = 0; KAuth::ExecuteJob* ExternalCommand::m_job; QCA::PrivateKey* ExternalCommand::privateKey; QCA::Initializer* ExternalCommand::init; @@ -144,7 +143,7 @@ bool ExternalCommand::start(int timeout) if (iface.isValid()) { QByteArray request; - request.setNum(++counter); + request.setNum(getNonce(iface)); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) request.append(argument.toUtf8()); @@ -204,7 +203,7 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) if (iface.isValid()) { QByteArray request; - request.setNum(++counter); + request.setNum(getNonce(iface)); request.append(source.path().toUtf8()); request.append(QByteArray::number(source.firstByte())); request.append(QByteArray::number(source.length())); @@ -411,7 +410,7 @@ void ExternalCommand::stopHelper() QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); if (iface.isValid()) { QByteArray request; - request.setNum(++counter); + request.setNum(getNonce(iface)); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw)); } @@ -420,6 +419,29 @@ void ExternalCommand::stopHelper() delete init; } +unsigned long long ExternalCommand::getNonce(QDBusInterface& iface) +{ + QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("getNonce")); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall); + QEventLoop loop; + unsigned long long rval = 0; + + auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { + loop.exit(); + + if (watcher->isError()) + qWarning() << watcher->error(); + else { + QDBusPendingReply reply = *watcher; + rval = reply; + } + }; + + connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); + loop.exec(); + return rval; +} + void DBusThread::run() { if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface"))) { diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 9f24c9f..8111a70 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -37,6 +37,7 @@ namespace QCA { class PrivateKey; class Initializer; } class Report; class CopySource; class CopyTarget; +class QDBusInterface; struct ExternalCommandPrivate; class DBusThread : public QThread @@ -129,12 +130,13 @@ private: void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); + static unsigned long long getNonce(QDBusInterface& iface); private: std::unique_ptr d; // KAuth stuff - static unsigned int counter; + static unsigned long long m_Nonce; static KAuth::ExecuteJob *m_job; static QCA::Initializer *init; static QCA::PrivateKey *privateKey; diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index e12cccc..9078309 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -61,7 +61,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); - m_Counter = 0; + m_Nonce = m_Generator.generate(); HelperSupport::progressStep(QVariantMap()); auto timeout = [this] () { @@ -90,6 +90,15 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) return reply; } +/** Generates cryptographic nonce + * @return nonce +*/ +unsigned long long ExternalCommandHelper::getNonce() +{ + m_Nonce = m_Generator.generate(); + return m_Nonce; +} + /** Reads the given number of bytes from the sourceDevice into the given buffer. @param sourceDevice device or file to read from @param buffer buffer to store the bytes read in @@ -151,7 +160,7 @@ bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QStrin { QByteArray request; - request.setNum(++m_Counter); + request.setNum(m_Nonce); request.append(sourceDevice.toUtf8()); request.append(QByteArray::number(sourceFirstByte)); request.append(QByteArray::number(sourceLength)); @@ -248,9 +257,10 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr { QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QVariantMap reply; + reply[QStringLiteral("success")] = true; QByteArray request; - request.setNum(++m_Counter); + request.setNum(m_Nonce); request.append(command.toUtf8()); for (const auto &argument : arguments) request.append(argument.toUtf8()); @@ -281,7 +291,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr void ExternalCommandHelper::exit(const QByteArray& signature) { QByteArray request; - request.setNum(++m_Counter); + request.setNum(m_Nonce); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { qCritical() << xi18n("Invalid cryptographic signature"); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 60453ef..a2a309b 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -43,6 +44,7 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); + Q_SCRIPTABLE unsigned long long getNonce(); Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); Q_SCRIPTABLE void exit(const QByteArray& signature); @@ -53,7 +55,8 @@ private: QEventLoop m_loop; QCA::Initializer initializer; QCA::PublicKey m_publicKey; - unsigned int m_Counter; + QRandomGenerator64 m_Generator; + unsigned long long m_Nonce; QString m_command; QString m_sourceDevice; QProcess m_cmd; From 938ec7fa8b6084586dd8a006da36c46bff1508ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 11:03:25 +0100 Subject: [PATCH 166/175] Make ExternalCommandHelper::getNonce() reentrant. Store previously generated values of nonce, and remove them from the container when they are used. BUG: 396312 --- src/util/externalcommand.cpp | 18 +++++++++------ src/util/externalcommand.h | 6 ++--- src/util/externalcommandhelper.cpp | 35 +++++++++++++++++++++--------- src/util/externalcommandhelper.h | 12 +++++----- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index a1030c0..443e37e 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -142,8 +142,8 @@ bool ExternalCommand::start(int timeout) bool rval = false; if (iface.isValid()) { QByteArray request; - - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) request.append(argument.toUtf8()); @@ -154,6 +154,7 @@ bool ExternalCommand::start(int timeout) QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), privateKey->signMessage(hash, QCA::EMSA3_Raw), + nonce, cmd, args(), d->m_Input, @@ -203,7 +204,8 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) if (iface.isValid()) { QByteArray request; - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); request.append(source.path().toUtf8()); request.append(QByteArray::number(source.firstByte())); request.append(QByteArray::number(source.length())); @@ -214,8 +216,9 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); // Use asynchronous DBus calls, so that we can process reports and progress - QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), + QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("copyblocks"), privateKey->signMessage(hash, QCA::EMSA3_Raw), + nonce, source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); @@ -410,16 +413,17 @@ void ExternalCommand::stopHelper() QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); if (iface.isValid()) { QByteArray request; - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); - iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw)); + iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw), nonce); } delete privateKey; delete init; } -unsigned long long ExternalCommand::getNonce(QDBusInterface& iface) +quint64 ExternalCommand::getNonce(QDBusInterface& iface) { QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("getNonce")); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 8111a70..233df12 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -130,13 +130,13 @@ private: void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); - static unsigned long long getNonce(QDBusInterface& iface); + static quint64 getNonce(QDBusInterface& iface); private: std::unique_ptr d; - // KAuth stuff - static unsigned long long m_Nonce; + // KAuth + static quint64 m_Nonce; static KAuth::ExecuteJob *m_job; static QCA::Initializer *init; static QCA::PrivateKey *privateKey; diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 9078309..d542324 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -61,7 +61,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); - m_Nonce = m_Generator.generate(); HelperSupport::progressStep(QVariantMap()); auto timeout = [this] () { @@ -93,10 +92,11 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) /** Generates cryptographic nonce * @return nonce */ -unsigned long long ExternalCommandHelper::getNonce() +quint64 ExternalCommandHelper::getNonce() { - m_Nonce = m_Generator.generate(); - return m_Nonce; + quint64 nonce = m_Generator.generate(); + m_Nonces.insert(nonce); + return nonce; } /** Reads the given number of bytes from the sourceDevice into the given buffer. @@ -156,11 +156,16 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr return true; } -bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) +bool 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) { + if (m_Nonces.find(nonce) != m_Nonces.end()) + m_Nonces.erase( nonce ); + else + return false; + QByteArray request; - request.setNum(m_Nonce); + request.setNum(nonce); request.append(sourceDevice.toUtf8()); request.append(QByteArray::number(sourceFirstByte)); request.append(QByteArray::number(sourceLength)); @@ -253,14 +258,21 @@ bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QStrin return rval; } -QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) +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")); QVariantMap reply; reply[QStringLiteral("success")] = true; + if (m_Nonces.find(nonce) != m_Nonces.end()) + m_Nonces.erase( nonce ); + else { + reply[QStringLiteral("success")] = false; + return reply; + } + QByteArray request; - request.setNum(m_Nonce); + request.setNum(nonce); request.append(command.toUtf8()); for (const auto &argument : arguments) request.append(argument.toUtf8()); @@ -288,10 +300,13 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr return reply; } -void ExternalCommandHelper::exit(const QByteArray& signature) +void ExternalCommandHelper::exit(const QByteArray& signature, const quint64 nonce) { QByteArray request; - request.setNum(m_Nonce); + if (m_Nonces.find(nonce) == m_Nonces.end()) + return; + + request.setNum(nonce); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { qCritical() << xi18n("Invalid cryptographic signature"); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index a2a309b..4f1cab7 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -18,6 +18,8 @@ #ifndef KPMCORE_EXTERNALCOMMANDHELPER_H #define KPMCORE_EXTERNALCOMMANDHELPER_H +#include + #include #include @@ -44,10 +46,10 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); - Q_SCRIPTABLE unsigned long long getNonce(); - Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); - Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); - Q_SCRIPTABLE void exit(const QByteArray& signature); + 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 bool 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 void exit(const QByteArray& signature, const quint64 nonce); private: void onReadOutput(); @@ -56,7 +58,7 @@ private: QCA::Initializer initializer; QCA::PublicKey m_publicKey; QRandomGenerator64 m_Generator; - unsigned long long m_Nonce; + std::unordered_set m_Nonces; QString m_command; QString m_sourceDevice; QProcess m_cmd; From 6b963fd26bd8e0c899ad7dc0aeba7bde1ce28b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 11:36:11 +0100 Subject: [PATCH 167/175] Move dependency list to the beginning of CMakeLists.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit – Require util-linux 2.32 – KF5 5.25 --- CMakeLists.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae7c043..8931813 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,15 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(CMAKE_USE_RELATIVE_PATHS OFF) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) +# Dependencies set(QT_MIN_VERSION "5.10.0") +set(KF5_MIN_VERSION "5.25") +set(BLKID_MIN_VERSION "2.32") +# Qca-qt5 + +# Runtime +# smartmontools 6.7 + set(VERSION_MAJOR "3") set(VERSION_MINOR "50") set(VERSION_RELEASE "0") @@ -32,7 +40,7 @@ add_definitions(-D'VERSION="${VERSION}"') #" set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(ECM 1.0.0 REQUIRED NO_MODULE) +find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") include(KDEInstallDirs) @@ -55,7 +63,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS ) # Load the frameworks we need -find_package(KF5 REQUIRED +find_package(KF5 ${KF5_MIN_VERSION} REQUIRED Auth I18n CoreAddons @@ -80,7 +88,7 @@ kde_enable_exceptions() if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(PkgConfig REQUIRED) - pkg_check_modules(BLKID REQUIRED blkid>=2.31.1) + pkg_check_modules(BLKID REQUIRED blkid>=${BLKID_MIN_VERSION}) endif() include_directories(${Qt5Core_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS} ${BLKID_INCLUDE_DIRS} lib/ src/) From 1b39be28ee6c5257ef8751763ed41e7c2d255656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 20:52:18 +0100 Subject: [PATCH 168/175] List supported QCA backends. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8931813..c3ac673 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) set(QT_MIN_VERSION "5.10.0") set(KF5_MIN_VERSION "5.25") set(BLKID_MIN_VERSION "2.32") -# Qca-qt5 +# Qca-qt5 (tested with botan and ossl backends) # Runtime # smartmontools 6.7 From 2579d042291f17c15ffd574a98102e591127bb4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 21:19:31 +0100 Subject: [PATCH 169/175] Remove ExternalCommand::waitFor. This is no longer used with KAuth. ExternalCommand::start now waits until command finishes. --- src/fs/fat12.cpp | 9 ++------- src/fs/fat32.cpp | 9 ++------- src/fs/jfs.cpp | 2 +- src/fs/luks.cpp | 10 ++++------ src/fs/luks2.cpp | 12 ++++++------ src/fs/ntfs.cpp | 2 -- src/fs/ocfs2.cpp | 13 +++++-------- src/fs/reiserfs.cpp | 2 +- src/plugins/sfdisk/sfdiskdevice.cpp | 2 +- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 4 ++-- src/util/externalcommand.cpp | 21 +-------------------- src/util/externalcommand.h | 1 - 12 files changed, 25 insertions(+), 62 deletions(-) diff --git a/src/fs/fat12.cpp b/src/fs/fat12.cpp index c059899..8124c4a 100644 --- a/src/fs/fat12.cpp +++ b/src/fs/fat12.cpp @@ -167,12 +167,7 @@ bool fat12::updateUUID(Report& report, const QString& deviceNode) const ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") }); - if (!cmd.write(QByteArray(uuid, sizeof(uuid)))) - return false; - - if (!cmd.start()) - return false; - - return cmd.waitFor(-1); + cmd.write(QByteArray(uuid, sizeof(uuid))); + return cmd.start(); } } diff --git a/src/fs/fat32.cpp b/src/fs/fat32.cpp index 4dfb2dd..b54e4fa 100644 --- a/src/fs/fat32.cpp +++ b/src/fs/fat32.cpp @@ -59,12 +59,7 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const // 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") }); - if (!cmd.write(QByteArray(uuid, sizeof(uuid)))) - return false; - - if (!cmd.start()) - return false; - - return cmd.waitFor(-1); + cmd.write(QByteArray(uuid, sizeof(uuid))); + return cmd.start(); } } diff --git a/src/fs/jfs.cpp b/src/fs/jfs.cpp index cc43573..dfb90a0 100644 --- a/src/fs/jfs.cpp +++ b/src/fs/jfs.cpp @@ -96,7 +96,7 @@ qint64 jfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode); - if (cmd.write(QByteArrayLiteral("dm")) && cmd.start() && cmd.waitFor()) { + if (cmd.write(QByteArrayLiteral("dm")) && cmd.start()) { qint64 blockSize = -1; QRegularExpression re(QStringLiteral("Block Size: (\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index a79b0f9..6215554 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -131,8 +131,7 @@ bool luks::create(Report& report, const QString& deviceNode) QStringLiteral("luksFormat"), deviceNode }); if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && - createCmd.start(-1) && - createCmd.waitFor() && createCmd.exitCode() == 0)) + createCmd.start(-1) && createCmd.exitCode() == 0)) { return false; } @@ -142,7 +141,7 @@ bool luks::create(Report& report, const QString& deviceNode) deviceNode, suggestedMapperName(deviceNode) }); - if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) + if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1))) return false; setPayloadSize(); @@ -267,8 +266,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) suggestedMapperName(deviceNode) }); if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') && - openCmd.start(-1) && - openCmd.waitFor() && openCmd.exitCode() == 0) ) + openCmd.start(-1) && openCmd.exitCode() == 0) ) return false; if (m_innerFs) { @@ -691,7 +689,7 @@ void luks::setPayloadSize() bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode }); - if (cmd.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.waitFor() && cmd.exitCode() == 0) + if (cmd.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.exitCode() == 0) return true; return false; diff --git a/src/fs/luks2.cpp b/src/fs/luks2.cpp index 107f51c..dfc9db0 100644 --- a/src/fs/luks2.cpp +++ b/src/fs/luks2.cpp @@ -57,7 +57,7 @@ bool luks2::create(Report& report, const QString& deviceNode) QStringLiteral("luksFormat"), deviceNode }); if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && - createCmd.start(-1) && createCmd.waitFor() && createCmd.exitCode() == 0)) + createCmd.start(-1) && createCmd.exitCode() == 0)) { return false; } @@ -67,7 +67,7 @@ bool luks2::create(Report& report, const QString& deviceNode) deviceNode, suggestedMapperName(deviceNode) }); - if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) + if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1))) return false; setPayloadSize(); @@ -99,8 +99,8 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); } - cryptResizeCmd.start(-1); - cryptResizeCmd.waitFor(); + if (!cryptResizeCmd.start(-1)) + return false; if ( cryptResizeCmd.exitCode() == 0 ) return m_innerFs->resize(report, mapperName(), m_PayloadSize); } @@ -115,8 +115,8 @@ bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); } - cryptResizeCmd.start(-1); - cryptResizeCmd.waitFor(); + if (!cryptResizeCmd.start(-1)) + return false; if ( cryptResizeCmd.exitCode() == 0 ) return true; } diff --git a/src/fs/ntfs.cpp b/src/fs/ntfs.cpp index 043d5de..471638a 100644 --- a/src/fs/ntfs.cpp +++ b/src/fs/ntfs.cpp @@ -195,7 +195,6 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const Log() << xi18nc("@info:progress", "Could not write new start sector to partition %1 when trying to update the NTFS boot sector.", deviceNode); return false; } - cmd.waitFor(-1); // 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 @@ -207,7 +206,6 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const Log() << xi18nc("@info:progress", "Could not write new start sector to partition %1 when trying to update the NTFS boot sector.", deviceNode); return false; } - cmd2.waitFor(-1); Log() << xi18nc("@info:progress", "Updated NTFS boot sector for partition %1 successfully.", deviceNode); diff --git a/src/fs/ocfs2.cpp b/src/fs/ocfs2.cpp index 8f2e914..af8eaaa 100644 --- a/src/fs/ocfs2.cpp +++ b/src/fs/ocfs2.cpp @@ -113,15 +113,12 @@ bool ocfs2::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.ocfs2"), { deviceNode }); - if (cmd.write("y\n")) - { - cmd.start(); - cmd.waitFor(-1); - - return cmd.exitCode() == 0; - } - else + cmd.write("y\n"); + if (!cmd.start()) return false; + + return cmd.exitCode() == 0; + } bool ocfs2::resize(Report& report, const QString& deviceNode, qint64 length) const diff --git a/src/fs/reiserfs.cpp b/src/fs/reiserfs.cpp index ddd3de3..5bfeb06 100644 --- a/src/fs/reiserfs.cpp +++ b/src/fs/reiserfs.cpp @@ -162,7 +162,7 @@ bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length) if (!cmd.start(-1)) return false; - return cmd.waitFor(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 256); + return cmd.exitCode() == 0 || cmd.exitCode() == 256; } bool reiserfs::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const diff --git a/src/plugins/sfdisk/sfdiskdevice.cpp b/src/plugins/sfdisk/sfdiskdevice.cpp index d8e1887..b866e7e 100644 --- a/src/plugins/sfdisk/sfdiskdevice.cpp +++ b/src/plugins/sfdisk/sfdiskdevice.cpp @@ -73,7 +73,7 @@ bool SfdiskDevice::createPartitionTable(Report& report, const PartitionTable& pt ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { m_device->deviceNode() } ); if ( createCommand.write(QByteArrayLiteral("label: ") + tableType + - QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) ) { return createCommand.output().contains(QStringLiteral("Script header accepted.")); } diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index ebaeedd..4e24de5 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -77,7 +77,7 @@ QString SfdiskPartitionTable::createPartition(Report& report, const Partition& p ExternalCommand createCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), QStringLiteral("--append"), partition.devicePath() } ); if ( createCommand.write(QByteArrayLiteral("start=") + QByteArray::number(partition.firstSector()) + type + - QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) && createCommand.waitFor() ) { + QByteArrayLiteral(" size=") + QByteArray::number(partition.length()) + QByteArrayLiteral("\nwrite\n")) && createCommand.start(-1) ) { QRegularExpression re(QStringLiteral("Created a new partition (\\d+)")); QRegularExpressionMatch rem = re.match(createCommand.output()); @@ -110,7 +110,7 @@ bool SfdiskPartitionTable::updateGeometry(Report& report, const Partition& parti if ( sfdiskCommand.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) + QByteArrayLiteral(" size=") + QByteArray::number(sectorEnd - sectorStart + 1) + QByteArrayLiteral("\nY\n")) - && sfdiskCommand.start(-1) && sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) { + && sfdiskCommand.start(-1) && sfdiskCommand.exitCode() == 0) { return true; } diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 443e37e..ceb4848 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -251,32 +251,13 @@ bool ExternalCommand::write(const QByteArray& input) return true; } -/** Waits for the external command to finish. - @param timeout timeout to wait until the process finishes. - @return true on success -*/ -bool ExternalCommand::waitFor(int timeout) -{ -// closeWriteChannel(); -/* - if (!waitForFinished(timeout)) { - if (report()) - report()->line() << xi18nc("@info:status", "(Command timeout while running)"); - return false; - }*/ - -// onReadOutput(); - Q_UNUSED(timeout) - return true; -} - /** Runs the command. @param timeout timeout to use for waiting when starting and when waiting for the process to finish @return true on success */ bool ExternalCommand::run(int timeout) { - return start(timeout) && waitFor(timeout)/* && exitStatus() == 0*/; + return start(timeout) /* && exitStatus() == 0*/; } void ExternalCommand::onReadOutput() diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 233df12..85577be 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -88,7 +88,6 @@ public: bool startCopyBlocks(); bool start(int timeout = 30000); - bool waitFor(int timeout = 30000); bool run(int timeout = 30000); /**< @return the exit code */ From 3d6aa8c3335372ab8a982337d6faabce32ce2af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 21:29:36 +0100 Subject: [PATCH 170/175] Remove ExternalCommand::onFinished. --- src/util/externalcommand.cpp | 6 ------ src/util/externalcommand.h | 1 - 2 files changed, 7 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index ceb4848..86e10f3 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -276,12 +276,6 @@ void ExternalCommand::onReadOutput() // *report() << QString::fromLocal8Bit(s); } -void ExternalCommand::onFinished(int exitCode, QProcess::ExitStatus exitStatus) -{ - Q_UNUSED(exitStatus) - setExitCode(exitCode); -} - void ExternalCommand::setCommand(const QString& cmd) { d->m_Command = cmd; diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 85577be..14b7c2f 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -127,7 +127,6 @@ public Q_SLOTS: private: void setExitCode(int i); - void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); static quint64 getNonce(QDBusInterface& iface); From 75bfd09c9c24a13a7589a13aa46c4fd149d30471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 22 Jul 2018 12:42:10 +0100 Subject: [PATCH 171/175] Fix detection of NTFS partitions BUG: 396749 --- src/plugins/sfdisk/sfdiskbackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 357c6db..31e7dd8 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -399,7 +399,7 @@ FileSystem::Type SfdiskBackend::detectFileSystem(const QString& partitionPath) else if (s == QStringLiteral("ext3")) rval = FileSystem::Type::Ext3; else if (s.startsWith(QStringLiteral("ext4"))) rval = FileSystem::Type::Ext4; else if (s == QStringLiteral("swap")) rval = FileSystem::Type::LinuxSwap; - else if (s == QStringLiteral("ntfs-3g")) rval = FileSystem::Type::Ntfs; + else if (s == QStringLiteral("ntfs")) rval = FileSystem::Type::Ntfs; else if (s == QStringLiteral("reiserfs")) rval = FileSystem::Type::ReiserFS; else if (s == QStringLiteral("reiser4")) rval = FileSystem::Type::Reiser4; else if (s == QStringLiteral("xfs")) rval = FileSystem::Type::Xfs; From 4b723be58547b4db803fc4e51ee124a67a3cc1cf Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Mon, 23 Jul 2018 13:34:40 -0300 Subject: [PATCH 172/175] Adding LvmDevice::s_OrphanPVs shared list to store PVs paths that are member of VGs that will be deleted soon. --- src/core/lvmdevice.cpp | 8 ++++++++ src/core/lvmdevice.h | 1 + src/ops/removevolumegroupoperation.cpp | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 96957be..203fb0b 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -83,6 +83,12 @@ LvmDevice::LvmDevice(const QString& vgName, const QString& iconName) */ QVector LvmDevice::s_DirtyPVs; + +/** + * shared list of PVs paths that are member of VGs that will be deleted soon. + */ +QVector LvmDevice::s_OrphanPVs; + LvmDevice::~LvmDevice() { } @@ -199,6 +205,8 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl */ void LvmDevice::scanSystemLVM(QList& devices) { + LvmDevice::s_OrphanPVs.clear(); + QList lvmList; for (const auto &vgName : getVGs()) { lvmList.append(new LvmDevice(vgName)); diff --git a/src/core/lvmdevice.h b/src/core/lvmdevice.h index f4413d8..089719b 100644 --- a/src/core/lvmdevice.h +++ b/src/core/lvmdevice.h @@ -55,6 +55,7 @@ public: qint64 partitionSize(QString& partitionPath) const override; static QVector s_DirtyPVs; + static QVector s_OrphanPVs; static void scanSystemLVM(QList& devices); diff --git a/src/ops/removevolumegroupoperation.cpp b/src/ops/removevolumegroupoperation.cpp index 605de3b..1c16433 100644 --- a/src/ops/removevolumegroupoperation.cpp +++ b/src/ops/removevolumegroupoperation.cpp @@ -18,6 +18,7 @@ #include "ops/removevolumegroupoperation.h" #include "jobs/removevolumegroupjob.h" +#include "core/lvmdevice.h" #include "core/partition.h" #include "core/partitiontable.h" #include "core/volumemanagerdevice.h" @@ -45,11 +46,28 @@ QString RemoveVolumeGroupOperation::description() const void RemoveVolumeGroupOperation::preview() { m_PartitionTable = device().partitionTable(); + + if (device().type() == Device::Type::LVM_Device) { + LvmDevice& lvm = static_cast(device()); + + LvmDevice::s_OrphanPVs << lvm.physicalVolumes(); + } + device().setPartitionTable(new PartitionTable(PartitionTable::vmd, 0, device().totalLogical() - 1)); } void RemoveVolumeGroupOperation::undo() { + if (device().type() == Device::Type::LVM_Device) { + LvmDevice& lvm = static_cast(device()); + + const QVector constOrphanList = LvmDevice::s_OrphanPVs; + + for (const Partition* p : constOrphanList) + if (lvm.physicalVolumes().contains(p)) + LvmDevice::s_OrphanPVs.removeAll(p); + } + device().setPartitionTable(m_PartitionTable); } From 700dddb875e3eeeb360009692155e1b620ba2690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Mon, 23 Jul 2018 22:52:59 +0100 Subject: [PATCH 173/175] Do not reassemble RAID devices after partition table commit. Reassembling RAID devices causes devices to disappear and reappear with a different name. --- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index 4e24de5..d7f84c6 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -57,8 +57,6 @@ bool SfdiskPartitionTable::commit(quint32 timeout) ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run(); ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("trigger") }).run(); - SoftwareRAID::reassembleSoftwareRAID(m_device->deviceNode()); - return true; } From 8b28001ae2a6931ba595451557cf2fbf88110f0c Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Tue, 24 Jul 2018 03:12:02 -0300 Subject: [PATCH 174/175] Pausing udev events during commit of RAID partition tables to map its logical partitions. --- src/plugins/sfdisk/sfdiskpartitiontable.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/sfdisk/sfdiskpartitiontable.cpp b/src/plugins/sfdisk/sfdiskpartitiontable.cpp index d7f84c6..470e783 100644 --- a/src/plugins/sfdisk/sfdiskpartitiontable.cpp +++ b/src/plugins/sfdisk/sfdiskpartitiontable.cpp @@ -53,10 +53,16 @@ bool SfdiskPartitionTable::open() bool SfdiskPartitionTable::commit(quint32 timeout) { + if (m_device->type() == Device::Type::SoftwareRAID_Device) + ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--stop-exec-queue") }).run(); + ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("settle"), QStringLiteral("--timeout=") + QString::number(timeout) }).run(); ExternalCommand(QStringLiteral("blockdev"), { QStringLiteral("--rereadpt"), m_device->deviceNode() }).run(); ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("trigger") }).run(); + if (m_device->type() == Device::Type::SoftwareRAID_Device) + ExternalCommand(QStringLiteral("udevadm"), { QStringLiteral("control"), QStringLiteral("--start-exec-queue") }).run(); + return true; } From 4fcbb540e05988c7cb73c091ca912756933a3e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Tue, 24 Jul 2018 21:39:55 +0100 Subject: [PATCH 175/175] Fix unallocated space calculation in the presence of LVM RAID partitions. BUG: 396776 --- src/core/partitiontable.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/core/partitiontable.cpp b/src/core/partitiontable.cpp index f5a4322..72c0693 100644 --- a/src/core/partitiontable.cpp +++ b/src/core/partitiontable.cpp @@ -402,18 +402,26 @@ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64 } } - // Take care of the free space between the end of the last child and the end - // of the device or the extended partition. - qint64 parentEnd = lastUsable(); - - if (!p->isRoot()) { - Partition* extended = dynamic_cast(p); - parentEnd = extended ? extended->lastSector() : -1; - Q_ASSERT(extended); + if (d.type() == Device::Type::LVM_Device) + { + const LvmDevice& lvm = static_cast(d); + p->insert(createUnallocated(d, *p, lastEnd, lastEnd + lvm.freePE() - 1)); } + else + { + // Take care of the free space between the end of the last child and the end + // of the device or the extended partition. + qint64 parentEnd = lastUsable(); - if (parentEnd >= firstUsable() && parentEnd >= lastEnd) - p->insert(createUnallocated(d, *p, lastEnd, parentEnd)); + if (!p->isRoot()) { + Partition* extended = dynamic_cast(p); + parentEnd = extended ? extended->lastSector() : -1; + Q_ASSERT(extended); + } + + if (parentEnd >= firstUsable() && parentEnd >= lastEnd) + p->insert(createUnallocated(d, *p, lastEnd, parentEnd)); + } } /** Updates the unallocated Partitions for this PartitionTable.