From b3e82d7c75112275f06f65bd3013e12154172147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sun, 4 Sep 2016 23:32:00 +0100 Subject: [PATCH] Cache LUKS specific variables during initial scan. --- src/core/lvmdevice.cpp | 7 +- src/fs/extended.h | 2 +- src/fs/filesystem.cpp | 9 +- src/fs/filesystem.h | 1 + src/fs/luks.cpp | 134 +++++++++++---------- src/fs/luks.h | 32 +++-- src/ops/restoreoperation.cpp | 6 +- src/plugins/libparted/libpartedbackend.cpp | 7 +- 8 files changed, 119 insertions(+), 79 deletions(-) diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 21a1d18..4bda317 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -124,6 +124,7 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl FileSystem::Type type = FileSystem::detectFileSystem(lvPath); FileSystem* fs = FileSystemFactory::create(type, 0, lvSize - 1); + fs->scan(lvPath); bool mounted = isMounted(lvPath); QString mountPoint = QString(); @@ -136,13 +137,13 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl if (type == FileSystem::Luks) { r |= PartitionRole::Luks; FS::luks* luksFs = static_cast(fs); - QString mapperNode = FS::luks::mapperName(lvPath); + QString mapperNode = luksFs->mapperName(); bool isCryptOpen = !mapperNode.isEmpty(); luksFs->setCryptOpen(isCryptOpen); luksFs->setLogicalSectorSize(logicalSize()); if (isCryptOpen) { - luksFs->loadInnerFileSystem(lvPath, mapperNode); + luksFs->loadInnerFileSystem(mapperNode); mountPoint = mountPointList.findByDevice(mapperNode) ? mountPointList.findByDevice(mapperNode)->mountPoint() : QString(); @@ -152,7 +153,7 @@ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTabl if (mounted) { const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint); if (freeSpaceInfo.isValid() && mountPoint != QString()) - luksFs->setSectorsUsed((freeSpaceInfo.used() + luksFs->getPayloadOffset(lvPath)) / logicalSize()); + luksFs->setSectorsUsed((freeSpaceInfo.used() + luksFs->payloadOffset()) / logicalSize()); } } else { mounted = false; diff --git a/src/fs/extended.h b/src/fs/extended.h index 4ba4d0d..08a14b3 100644 --- a/src/fs/extended.h +++ b/src/fs/extended.h @@ -44,7 +44,7 @@ public: public: - bool create(Report&, const QString&) const override; + bool create(Report&, const QString&) const override; CommandSupportType supportCreate() const override { return m_Create; diff --git a/src/fs/filesystem.cpp b/src/fs/filesystem.cpp index dd3aef7..2a0ab4c 100644 --- a/src/fs/filesystem.cpp +++ b/src/fs/filesystem.cpp @@ -140,6 +140,14 @@ bool FileSystem::create(Report& report, const QString& deviceNode) const return true; } +/** Scans a new FileSystem and load file system specific class variables. + * @param deviceNode the device node for the Partition to create the FileSystem on +*/ +void FileSystem::scan(const QString& deviceNode) +{ + Q_UNUSED(deviceNode); +} + /** Resize a FileSystem to a given new length @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @@ -172,7 +180,6 @@ bool FileSystem::resizeOnline(Report& report, const QString& deviceNode, const Q return true; } - /** Move a FileSystem to a new start sector @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on diff --git a/src/fs/filesystem.h b/src/fs/filesystem.h index 53d84a2..ab5b776 100644 --- a/src/fs/filesystem.h +++ b/src/fs/filesystem.h @@ -108,6 +108,7 @@ public: public: virtual void init() {}; + virtual void scan(const QString& deviceNode); virtual qint64 readUsedCapacity(const QString& deviceNode) const; virtual QString readLabel(const QString& deviceNode) const; virtual bool create(Report& report, const QString& deviceNode) const; diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp index c881f7a..d3fd9e7 100644 --- a/src/fs/luks.cpp +++ b/src/fs/luks.cpp @@ -88,6 +88,16 @@ void luks::init() m_GetUsed = cmdSupportNone; // libparted does not support LUKS, we do this as a special case } +void luks::scan(const QString& deviceNode) +{ + getMapperName(deviceNode); + getCipherName(deviceNode); + getCipherMode(deviceNode); + getHashName(deviceNode); + getKeySize(deviceNode); + getPayloadOffset(deviceNode); +} + bool luks::supportToolFound() const { m_cryptsetupFound = findExternal(QStringLiteral("cryptsetup")) ? cmdSupportFileSystem : cmdSupportNone; @@ -129,11 +139,12 @@ bool luks::create(Report& report, const QString& deviceNode) const if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toUtf8() + '\n') == m_passphrase.toUtf8().length() + 1 && openCmd.waitFor())) return false; - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + if (mapperName().isEmpty()) return false; - if (!m_innerFs->create(report, mapperNode)) +// FIXME scan(deviceNode); + + if (!m_innerFs->create(report, mapperName())) return false; return true; @@ -169,20 +180,20 @@ QString luks::passphrase() const return m_passphrase; } -bool luks::canMount(const QString& deviceNode, const QString& mountPoint) const +bool luks::canMount(const QString&, const QString& mountPoint) const { return m_isCryptOpen && !m_isMounted && m_innerFs && - m_innerFs->canMount(mapperName(deviceNode), mountPoint); + m_innerFs->canMount(mapperName(), mountPoint); } -bool luks::canUnmount(const QString& deviceNode) const +bool luks::canUnmount(const QString&) const { return m_isCryptOpen && m_isMounted && m_innerFs && - m_innerFs->canUnmount(mapperName(deviceNode)); + m_innerFs->canUnmount(mapperName()); } bool luks::isMounted() const @@ -219,7 +230,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) { if (m_isCryptOpen) { - if (!mapperName(deviceNode).isEmpty()) + if (!mapperName().isEmpty()) { qWarning() << "LUKS device" << deviceNode << "already decrypted." @@ -252,17 +263,17 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) openCmd.waitFor() && openCmd.exitCode() == 0) ) return false; - if (m_innerFs) - { + if (m_innerFs) { delete m_innerFs; m_innerFs = nullptr; } - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + scan(deviceNode); + + if (mapperName().isEmpty()) return false; - loadInnerFileSystem(deviceNode, mapperNode); + loadInnerFileSystem(mapperName()); m_isCryptOpen = (m_innerFs != nullptr); if (!m_isCryptOpen) @@ -289,7 +300,7 @@ bool luks::cryptClose(const QString& deviceNode) } ExternalCommand cmd(QStringLiteral("cryptsetup"), - { QStringLiteral("close"), mapperName(deviceNode) }); + { QStringLiteral("close"), mapperName() }); if (!(cmd.run(-1) && cmd.exitCode() == 0)) return false; @@ -308,7 +319,7 @@ bool luks::cryptClose(const QString& deviceNode) return true; } -void luks::loadInnerFileSystem(const QString& deviceNode, const QString& mapperNode) +void luks::loadInnerFileSystem(const QString& mapperNode) { Q_ASSERT(!m_innerFs); FileSystem::Type innerFsType = detectFileSystem(mapperNode); @@ -317,7 +328,7 @@ void luks::loadInnerFileSystem(const QString& deviceNode, const QString& mapperN setLabel(m_innerFs->readLabel(mapperNode)); setUUID(m_innerFs->readUUID(mapperNode)); if (m_innerFs->supportGetUsed() == FileSystem::cmdSupportFileSystem) - setSectorsUsed((m_innerFs->readUsedCapacity(mapperNode) + getPayloadOffset(deviceNode)) / m_logicalSectorSize ); + setSectorsUsed((m_innerFs->readUsedCapacity(mapperNode) + payloadOffset()) / m_logicalSectorSize ); } void luks::createInnerFileSystem(FileSystem::Type type) @@ -326,15 +337,14 @@ void luks::createInnerFileSystem(FileSystem::Type type) m_innerFs = FileSystemFactory::cloneWithNewType(type, *this); } -bool luks::check(Report& report, const QString& deviceNode) const +bool luks::check(Report& report, const QString&) const { Q_ASSERT(m_innerFs); - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + if (mapperName().isEmpty()) return false; - return m_innerFs->check(report, mapperNode); + return m_innerFs->check(report, mapperName()); } qint64 luks::readUsedCapacity(const QString& deviceNode) const @@ -364,19 +374,18 @@ bool luks::mount(Report& report, const QString& deviceNode, const QString& mount Q_ASSERT(m_innerFs); - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + if (mapperName().isEmpty()) return false; - if (m_innerFs->canMount(mapperNode, mountPoint)) + if (m_innerFs->canMount(mapperName(), mountPoint)) { - if (m_innerFs->mount(report, mapperNode, mountPoint)) + if (m_innerFs->mount(report, mapperName(), mountPoint)) { m_isMounted = true; const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint); if (freeSpaceInfo.isValid() && mountPoint != QString()) - setSectorsUsed((freeSpaceInfo.used() + getPayloadOffset(deviceNode)) / m_logicalSectorSize); + setSectorsUsed((freeSpaceInfo.used() + payloadOffset()) / m_logicalSectorSize); return true; } @@ -385,7 +394,7 @@ bool luks::mount(Report& report, const QString& deviceNode, const QString& mount ExternalCommand mountCmd( report, QStringLiteral("mount"), - { QStringLiteral("--verbose"), mapperNode, mountPoint }); + { QStringLiteral("--verbose"), mapperName(), mountPoint }); if (mountCmd.run() && mountCmd.exitCode() == 0) { m_isMounted = true; @@ -413,13 +422,12 @@ bool luks::unmount(Report& report, const QString& deviceNode) Q_ASSERT(m_innerFs); - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + if (mapperName().isEmpty()) return false; - if (m_innerFs->canUnmount(mapperNode)) + if (m_innerFs->canUnmount(mapperName())) { - if (m_innerFs->unmount(report, mapperNode)) + if (m_innerFs->unmount(report, mapperName())) { m_isMounted = false; return true; @@ -428,7 +436,7 @@ bool luks::unmount(Report& report, const QString& deviceNode) else { ExternalCommand unmountCmd( report, QStringLiteral("umount"), - { QStringLiteral("--verbose"), QStringLiteral("--all-targets"), mapperNode }); + { QStringLiteral("--verbose"), QStringLiteral("--all-targets"), mapperName() }); if (unmountCmd.run() && unmountCmd.exitCode() == 0) { m_isMounted = false; @@ -450,43 +458,42 @@ QString luks::suggestedMapperName(const QString& deviceNode) const return QStringLiteral("luks-") + readOuterUUID(deviceNode); } -QString luks::readLabel(const QString& deviceNode) const +QString luks::readLabel(const QString&) const { if (m_isCryptOpen && m_innerFs) - return m_innerFs->readLabel(mapperName(deviceNode)); + return m_innerFs->readLabel(mapperName()); return QString(); } -bool luks::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) +bool luks::writeLabel(Report& report, const QString&, const QString& newLabel) { Q_ASSERT(m_innerFs); - return m_innerFs->writeLabel(report, mapperName(deviceNode), newLabel); + return m_innerFs->writeLabel(report, mapperName(), newLabel); } bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) const { Q_ASSERT(m_innerFs); - QString mapperNode = mapperName(deviceNode); - if (mapperNode.isEmpty()) + if (mapperName().isEmpty()) return false; - qint64 payloadLength = newLength - getPayloadOffset(deviceNode); + qint64 payloadLength = newLength - payloadOffset(); if ( newLength - length() * m_logicalSectorSize > 0 ) { - ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperNode }); + ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) { - return m_innerFs->resize(report, mapperNode, payloadLength); + return m_innerFs->resize(report, mapperName(), payloadLength); } } - else if (m_innerFs->resize(report, mapperNode, payloadLength)) + else if (m_innerFs->resize(report, mapperName(), payloadLength)) { ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("--size"), QString::number(payloadLength / /*m_logicalSectorSize*/ 512), // LUKS assume 512 bytes sector - QStringLiteral("resize"), mapperNode }); + QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) { @@ -500,7 +507,7 @@ bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) c QString luks::readUUID(const QString& deviceNode) const { if (m_isCryptOpen && m_innerFs) - return m_innerFs->readUUID(mapperName(deviceNode)); + return m_innerFs->readUUID(mapperName()); return readOuterUUID(deviceNode); } @@ -527,7 +534,7 @@ bool luks::updateUUID(Report& report, const QString& deviceNode) const return cmd.run(-1) && cmd.exitCode() == 0; } -QString luks::mapperName(const QString& deviceNode) +void luks::getMapperName(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("lsblk"), { QStringLiteral("--list"), @@ -539,12 +546,13 @@ QString luks::mapperName(const QString& deviceNode) QStringList output=cmd.output().split(QStringLiteral("\n")); output.removeFirst(); if (!output.first().isEmpty()) - return QStringLiteral("/dev/mapper/") + output.first(); + m_MapperName = QStringLiteral("/dev/mapper/") + output.first(); } - return QString(); + else + m_MapperName = QString(); } -QString luks::getCipherName(const QString& deviceNode) const +void luks::getCipherName(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); @@ -552,12 +560,13 @@ QString luks::getCipherName(const QString& deviceNode) const QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)")); QRegularExpressionMatch reCipherName = re.match(cmd.output()); if (reCipherName.hasMatch()) - return reCipherName.captured(1); + m_CipherName = reCipherName.captured(1); } - return QStringLiteral("---"); + else + m_CipherName = QStringLiteral("---"); } -QString luks::getCipherMode(const QString& deviceNode) const +void luks::getCipherMode(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); @@ -565,12 +574,13 @@ QString luks::getCipherMode(const QString& deviceNode) const QRegularExpression re(QStringLiteral("Cipher mode:\\s+(\\w+)")); QRegularExpressionMatch reCipherMode = re.match(cmd.output()); if (reCipherMode.hasMatch()) - return reCipherMode.captured(1); + m_CipherMode = reCipherMode.captured(1); } - return QStringLiteral("---"); + else + m_CipherMode = QStringLiteral("---"); } -QString luks::getHashName(const QString& deviceNode) const +void luks::getHashName(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); @@ -578,12 +588,12 @@ QString luks::getHashName(const QString& deviceNode) const QRegularExpression re(QStringLiteral("Hash spec:\\s+(\\w+)")); QRegularExpressionMatch reHash = re.match(cmd.output()); if (reHash.hasMatch()) - return reHash.captured(1); + m_HashName = reHash.captured(1); } - return QStringLiteral("---"); + m_HashName = QStringLiteral("---"); } -qint64 luks::getKeySize(const QString& deviceNode) const +void luks::getKeySize(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); @@ -591,15 +601,16 @@ qint64 luks::getKeySize(const QString& deviceNode) const QRegularExpression re(QStringLiteral("MK bits:\\s+(\\d+)")); QRegularExpressionMatch reKeySize = re.match(cmd.output()); if (reKeySize.hasMatch()) - return reKeySize.captured(1).toLongLong(); + m_KeySize = reKeySize.captured(1).toLongLong(); } - return -1; + else + m_KeySize = -1; } /* * @return size of payload offset in bytes. */ -qint64 luks::getPayloadOffset(const QString& deviceNode) const +void luks::getPayloadOffset(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); @@ -607,9 +618,10 @@ qint64 luks::getPayloadOffset(const QString& deviceNode) const QRegularExpression re(QStringLiteral("Payload offset:\\s+(\\d+)")); QRegularExpressionMatch rePayloadOffset = re.match(cmd.output()); if (rePayloadOffset.hasMatch()) - return rePayloadOffset.captured(1).toLongLong() * 512; // assuming LUKS sector size is 512 + m_KeySize = rePayloadOffset.captured(1).toLongLong() * 512; // assuming LUKS sector size is 512 } - return -1; + else + m_KeySize = -1; } bool luks::canEncryptType(FileSystem::Type type) diff --git a/src/fs/luks.h b/src/fs/luks.h index 8ffc00c..0348948 100644 --- a/src/fs/luks.h +++ b/src/fs/luks.h @@ -45,6 +45,7 @@ public: public: void init() override; + void scan(const QString& deviceNode) override; qint64 readUsedCapacity(const QString& deviceNode) const override; CommandSupportType supportGetUsed() const override { @@ -109,7 +110,7 @@ public: } bool check(Report& report, const QString& deviceNode) const override; - bool create(Report &report, const QString &deviceNode) const override; + bool create(Report& report, const QString& deviceNode) const override; SupportTool supportToolName() const override; bool supportToolFound() const override; QString readUUID(const QString& deviceNode) const override; @@ -139,7 +140,7 @@ public: bool cryptOpen(QWidget* parent, const QString& deviceNode); bool cryptClose(const QString& deviceNode); - void loadInnerFileSystem(const QString& deviceNode, const QString& mapperNode); + void loadInnerFileSystem(const QString& mapperNode); void createInnerFileSystem(Type type); bool mount(Report& report, const QString& deviceNode, const QString& mountPoint) override; @@ -149,13 +150,21 @@ public: QString suggestedMapperName(const QString& deviceNode) const; - static QString mapperName(const QString& deviceNode); + void getMapperName(const QString& deviceNode); + + void getCipherName(const QString& deviceNode); + void getCipherMode(const QString& deviceNode); + void getHashName(const QString& deviceNode); + void getKeySize(const QString& deviceNode); + void getPayloadOffset(const QString& deviceNode); + + QString mapperName() const { return m_MapperName; }; + QString cipherName() const { return m_CipherName; }; + QString cipherMode() const { return m_CipherMode; }; + QString hashName() const { return m_HashName; }; + qint64 keySize() const { return m_KeySize; }; + qint64 payloadOffset() const { return m_PayloadOffset; }; - QString getCipherName(const QString& deviceNode) const; - QString getCipherMode(const QString& deviceNode) const; - QString getHashName(const QString& deviceNode) const; - qint64 getKeySize(const QString& deviceNode) const; - qint64 getPayloadOffset(const QString& deviceNode) const; static bool canEncryptType(FileSystem::Type type); protected: @@ -183,6 +192,13 @@ private: QString m_passphrase; bool m_isMounted; unsigned int m_logicalSectorSize; + + QString m_MapperName; + QString m_CipherName; + QString m_CipherMode; + QString m_HashName; + qint64 m_KeySize; + qint64 m_PayloadOffset; }; } diff --git a/src/ops/restoreoperation.cpp b/src/ops/restoreoperation.cpp index 670d7b1..8423aeb 100644 --- a/src/ops/restoreoperation.cpp +++ b/src/ops/restoreoperation.cpp @@ -199,8 +199,10 @@ bool RestoreOperation::canRestore(const Partition* p) if (p->roles().has(PartitionRole::Extended)) return false; - if (p->roles().has(PartitionRole::Luks)) - return FS::luks::mapperName(p->deviceNode()).isEmpty(); + if (p->roles().has(PartitionRole::Luks)) { + const FS::luks* luksFs = static_cast(&p->fileSystem()); + return luksFs->mapperName().isEmpty(); + } return true; } diff --git a/src/plugins/libparted/libpartedbackend.cpp b/src/plugins/libparted/libpartedbackend.cpp index 57470aa..e5def75 100644 --- a/src/plugins/libparted/libpartedbackend.cpp +++ b/src/plugins/libparted/libpartedbackend.cpp @@ -238,6 +238,7 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) parent = d->partitionTable(); FileSystem* fs = FileSystemFactory::create(fsType, start, end); + fs->scan(partitionNode); // libparted does not handle LUKS partitions QString mountPoint; @@ -245,13 +246,13 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) if (fsType == FileSystem::Luks) { r |= PartitionRole::Luks; FS::luks* luksFs = static_cast(fs); - QString mapperNode = FS::luks::mapperName(partitionNode); + QString mapperNode = luksFs->mapperName(); bool isCryptOpen = !mapperNode.isEmpty(); luksFs->setCryptOpen(isCryptOpen); luksFs->setLogicalSectorSize(d->logicalSectorSize()); if (isCryptOpen) { - luksFs->loadInnerFileSystem(partitionNode, mapperNode); + luksFs->loadInnerFileSystem(mapperNode); if (luksFs->type() == FileSystem::Lvm2_PV) { mountPoint = FS::lvm2_pv::getVGName(mapperNode); @@ -270,7 +271,7 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) if (mounted) { const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint); if (freeSpaceInfo.isValid() && mountPoint != QString()) - luksFs->setSectorsUsed((freeSpaceInfo.used() + luksFs->getPayloadOffset(partitionNode)) / d->logicalSectorSize()); + luksFs->setSectorsUsed((freeSpaceInfo.used() + luksFs->payloadOffset()) / d->logicalSectorSize()); } } else { mounted = false;