File indexing completed on 2024-05-05 05:48:46

0001 /*
0002     SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
0003     SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas <andrius@stikonas.eu>
0004     SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
0005     SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
0006     SPDX-FileCopyrightText: 2017 Christian Morlok <christianmorlok@gmail.com>
0007     SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
0008     SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com>
0009     SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com>
0010 
0011     SPDX-License-Identifier: GPL-3.0-or-later
0012 */
0013 
0014 #include "fs/luks.h"
0015 #include "fs/lvm2_pv.h"
0016 
0017 #include "fs/filesystemfactory.h"
0018 
0019 #include "util/externalcommand.h"
0020 #include "util/capacity.h"
0021 #include "util/helpers.h"
0022 #include "util/report.h"
0023 
0024 #include <cmath>
0025 
0026 #include <QDebug>
0027 #include <QDialog>
0028 #include <QJsonArray>
0029 #include <QJsonObject>
0030 #include <QJsonDocument>
0031 #include <QRegularExpression>
0032 #include <QPointer>
0033 #include <QStorageInfo>
0034 #include <QString>
0035 #include <QUuid>
0036 #include <QWidget>
0037 
0038 #include <KLocalizedString>
0039 #include <KPasswordDialog>
0040 
0041 namespace FS
0042 {
0043 FileSystem::CommandSupportType luks::m_GetUsed = FileSystem::cmdSupportNone;
0044 FileSystem::CommandSupportType luks::m_GetLabel = FileSystem::cmdSupportNone;
0045 FileSystem::CommandSupportType luks::m_Create = FileSystem::cmdSupportNone;
0046 FileSystem::CommandSupportType luks::m_Grow = FileSystem::cmdSupportNone;
0047 FileSystem::CommandSupportType luks::m_Shrink = FileSystem::cmdSupportNone;
0048 FileSystem::CommandSupportType luks::m_Move = FileSystem::cmdSupportNone;
0049 FileSystem::CommandSupportType luks::m_Check = FileSystem::cmdSupportNone;
0050 FileSystem::CommandSupportType luks::m_Copy = FileSystem::cmdSupportNone;
0051 FileSystem::CommandSupportType luks::m_Backup = FileSystem::cmdSupportNone;
0052 FileSystem::CommandSupportType luks::m_SetLabel = FileSystem::cmdSupportNone;
0053 FileSystem::CommandSupportType luks::m_UpdateUUID = FileSystem::cmdSupportNone;
0054 FileSystem::CommandSupportType luks::m_GetUUID = FileSystem::cmdSupportNone;
0055 
0056 luks::luks(qint64 firstsector,
0057            qint64 lastsector,
0058            qint64 sectorsused,
0059            const QString& label,
0060            const QVariantMap& features,
0061            FileSystem::Type t)
0062     : FileSystem(firstsector, lastsector, sectorsused, label, features, t)
0063     , m_innerFs(nullptr)
0064     , m_isCryptOpen(false)
0065     , m_cryptsetupFound(m_Create != cmdSupportNone)
0066     , m_isMounted(false)
0067     , m_KeySize(-1)
0068     , m_PayloadOffset(-1)
0069 {
0070 }
0071 
0072 luks::~luks()
0073 {
0074     delete m_innerFs;
0075 }
0076 
0077 void luks::init()
0078 {
0079     CommandSupportType cryptsetupFound = findExternal(QStringLiteral("cryptsetup")) ? cmdSupportFileSystem : cmdSupportNone;
0080 
0081     m_Create     = cryptsetupFound;
0082     m_UpdateUUID = cryptsetupFound;
0083     m_GetUUID    = cryptsetupFound;
0084     m_Grow       = cryptsetupFound;
0085     m_Shrink     = cryptsetupFound;
0086 
0087     m_SetLabel = cmdSupportNone;
0088     m_GetLabel = cmdSupportFileSystem;
0089     m_Check = cmdSupportCore;
0090     m_Copy = cmdSupportCore;
0091     m_Move = cmdSupportCore;
0092     m_Backup = cmdSupportCore;
0093     m_GetUsed = cmdSupportNone; // libparted does not support LUKS, we do this as a special case
0094 }
0095 
0096 void luks::scan(const QString& deviceNode)
0097 {
0098     getMapperName(deviceNode);
0099     getLuksInfo(deviceNode);
0100 }
0101 
0102 bool luks::supportToolFound() const
0103 {
0104     return m_cryptsetupFound && ((m_isCryptOpen && m_innerFs) ? m_innerFs->supportToolFound() : true);
0105 }
0106 
0107 FileSystem::SupportTool luks::supportToolName() const
0108 {
0109     if (m_isCryptOpen && m_innerFs && m_cryptsetupFound)
0110         return m_innerFs->supportToolName();
0111     return SupportTool(QStringLiteral("cryptsetup"),
0112                        QUrl(QStringLiteral("https://code.google.com/p/cryptsetup/")));
0113 }
0114 
0115 bool luks::create(Report& report, const QString& deviceNode)
0116 {
0117     Q_ASSERT(m_innerFs);
0118     Q_ASSERT(!m_passphrase.isEmpty());
0119 
0120     ExternalCommand createCmd(report, QStringLiteral("cryptsetup"),
0121                               { QStringLiteral("-s"),
0122                                 QStringLiteral("512"),
0123                                 QStringLiteral("--batch-mode"),
0124                                 QStringLiteral("--force-password"),
0125                                 QStringLiteral("--type"), QStringLiteral("luks1"),
0126                                 QStringLiteral("luksFormat"),
0127                                 deviceNode });
0128     if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') &&
0129                 createCmd.start(-1) && createCmd.exitCode() == 0))
0130     {
0131         return false;
0132     }
0133 
0134     ExternalCommand openCmd(report, QStringLiteral("cryptsetup"),
0135                               { QStringLiteral("open"),
0136                                 deviceNode,
0137                                 suggestedMapperName(deviceNode) });
0138 
0139     if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1)))
0140         return false;
0141 
0142     setPayloadSize();
0143     scan(deviceNode);
0144 
0145     if (mapperName().isEmpty())
0146         return false;
0147 
0148     if (!m_innerFs->create(report, mapperName()))
0149         return false;
0150 
0151     return true;
0152 }
0153 
0154 bool luks::execChangePosixPermission(Report& report, const QString&)
0155 {
0156     return FileSystem::execChangePosixPermission(report, mapperName());
0157 }
0158 
0159 QString luks::mountTitle() const
0160 {
0161     return xi18nc("@title:menu", "Mount");
0162 }
0163 
0164 QString luks::unmountTitle() const
0165 {
0166     return xi18nc("@title:menu", "Unmount");
0167 }
0168 
0169 QString luks::cryptOpenTitle() const
0170 {
0171     return xi18nc("@title:menu", "Unlock");
0172 }
0173 
0174 QString luks::cryptCloseTitle() const
0175 {
0176     return xi18nc("@title:menu", "Lock");
0177 }
0178 
0179 void luks::setPassphrase(const QString& passphrase)
0180 {
0181     m_passphrase = passphrase;
0182 }
0183 
0184 QString luks::passphrase() const
0185 {
0186     return m_passphrase;
0187 }
0188 
0189 bool luks::canMount(const QString&, const QString& mountPoint) const
0190 {
0191     return m_isCryptOpen &&
0192            !m_isMounted &&
0193            m_innerFs &&
0194            m_innerFs->canMount(mapperName(), mountPoint);
0195 }
0196 
0197 bool luks::canUnmount(const QString&) const
0198 {
0199     return m_isCryptOpen &&
0200            m_isMounted &&
0201            m_innerFs &&
0202            m_innerFs->canUnmount(mapperName());
0203 }
0204 
0205 bool luks::isMounted() const
0206 {
0207     return m_isCryptOpen && m_isMounted;
0208 }
0209 
0210 void luks::setMounted(bool mounted)
0211 {
0212     m_isMounted = mounted;
0213 }
0214 
0215 bool luks::canCryptOpen(const QString&) const
0216 {
0217     return !m_isCryptOpen && !m_isMounted && supportToolFound();
0218 }
0219 
0220 bool luks::canCryptClose(const QString&) const
0221 {
0222     return m_isCryptOpen && !m_isMounted && m_cryptsetupFound;
0223 }
0224 
0225 bool luks::isCryptOpen() const
0226 {
0227     return m_isCryptOpen;
0228 }
0229 
0230 void luks::setCryptOpen(bool cryptOpen)
0231 {
0232     m_isCryptOpen = cryptOpen;
0233 }
0234 
0235 bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
0236 {
0237     if (m_isCryptOpen)
0238     {
0239         if (!mapperName().isEmpty())
0240         {
0241             qWarning() << "LUKS device" << deviceNode
0242                        << "already decrypted."
0243                        << "Cannot decrypt again.";
0244             return false;
0245         }
0246         else
0247         {
0248             qWarning() << "LUKS device" << deviceNode
0249                        << "reportedly decrypted but mapper node not found."
0250                        << "Marking device as NOT decrypted and trying to "
0251                           "decrypt again anyway.";
0252             m_isCryptOpen = false;
0253         }
0254     }
0255 
0256     KPasswordDialog dlg( parent );
0257     dlg.setPrompt(i18n("Enter passphrase for %1:", deviceNode));
0258     if( !dlg.exec() )
0259         return false;
0260 
0261     QString passphrase = dlg.password();
0262     ExternalCommand openCmd(QStringLiteral("cryptsetup"),
0263                               { QStringLiteral("open"),
0264                                 QStringLiteral("--tries"), QStringLiteral("1"),
0265                                 deviceNode,
0266                                 suggestedMapperName(deviceNode) });
0267 
0268     if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') &&
0269                     openCmd.start(-1) && openCmd.exitCode() == 0) )
0270         return false;
0271 
0272     if (m_innerFs) {
0273         delete m_innerFs;
0274         m_innerFs = nullptr;
0275     }
0276 
0277     scan(deviceNode);
0278 
0279     if (mapperName().isEmpty())
0280         return false;
0281 
0282     loadInnerFileSystem(mapperName());
0283     m_isCryptOpen = (m_innerFs != nullptr);
0284 
0285     if (!m_isCryptOpen)
0286         return false;
0287 
0288     for (auto &p : LVM::pvList::list())
0289         if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Type::Lvm2_PV)
0290             p.setLuks(false);
0291 
0292     m_passphrase = passphrase;
0293     return true;
0294 }
0295 
0296 bool luks::cryptClose(const QString& deviceNode)
0297 {
0298     if (!m_isCryptOpen)
0299     {
0300         qWarning() << "Cannot close LUKS device" << deviceNode
0301                    << "because it's not open.";
0302         return false;
0303     }
0304 
0305     if (m_isMounted)
0306     {
0307         qWarning() << "Cannot close LUKS device" << deviceNode
0308                    << "because the filesystem is mounted.";
0309         return false;
0310     }
0311 
0312     ExternalCommand cmd(QStringLiteral("cryptsetup"),
0313                         { QStringLiteral("close"), mapperName() });
0314     if (!(cmd.run(-1) && cmd.exitCode() == 0))
0315         return false;
0316 
0317     delete m_innerFs;
0318     m_innerFs = nullptr;
0319 
0320     m_passphrase.clear();
0321     setLabel(FileSystem::readLabel(deviceNode));
0322     setUUID(readUUID(deviceNode));
0323     setSectorsUsed(-1);
0324 
0325     m_isCryptOpen = (m_innerFs != nullptr);
0326 
0327     for (auto &p : LVM::pvList::list())
0328         if (!p.isLuks() && p.partition()->deviceNode() == deviceNode)
0329             p.setLuks(true);
0330 
0331     return true;
0332 }
0333 
0334 void luks::loadInnerFileSystem(const QString& mapperNode)
0335 {
0336     Q_ASSERT(!m_innerFs);
0337     FileSystem::Type innerFsType = detectFileSystem(mapperNode);
0338     m_innerFs = FileSystemFactory::cloneWithNewType(innerFsType,
0339                                                     *this);
0340     setLabel(m_innerFs->readLabel(mapperNode));
0341     setUUID(m_innerFs->readUUID(mapperNode));
0342     if (m_innerFs->supportGetUsed() == FileSystem::cmdSupportFileSystem)
0343         setSectorsUsed(static_cast<qint64>(std::ceil((m_innerFs->readUsedCapacity(mapperNode) + payloadOffset()) / static_cast<double>(sectorSize()) )));
0344     m_innerFs->scan(mapperNode);
0345 }
0346 
0347 void luks::createInnerFileSystem(FileSystem::Type type)
0348 {
0349     Q_ASSERT(!m_innerFs);
0350     m_innerFs = FileSystemFactory::cloneWithNewType(type, *this);
0351 }
0352 
0353 bool luks::check(Report& report, const QString&) const
0354 {
0355     Q_ASSERT(m_innerFs);
0356 
0357     if (mapperName().isEmpty())
0358         return false;
0359 
0360     return m_innerFs->check(report, mapperName());
0361 }
0362 
0363 qint64 luks::readUsedCapacity(const QString& deviceNode) const
0364 {
0365     if (!m_isCryptOpen)
0366         return -1;
0367     if (m_innerFs)
0368         return m_innerFs->readUsedCapacity(deviceNode);
0369     return -1;
0370 }
0371 
0372 bool luks::mount(Report& report, const QString& deviceNode, const QString& mountPoint)
0373 {
0374     if (!m_isCryptOpen)
0375     {
0376         qWarning() << "Cannot mount device" << deviceNode
0377                    << "before decrypting it first.";
0378         return false;
0379     }
0380 
0381     if (m_isMounted)
0382     {
0383         qWarning() << "Cannot mount device" << deviceNode
0384                    << "because it's already mounted.";
0385         return false;
0386     }
0387 
0388     Q_ASSERT(m_innerFs);
0389 
0390     if (mapperName().isEmpty())
0391         return false;
0392 
0393     if (m_innerFs->canMount(mapperName(), mountPoint))
0394     {
0395         if (m_innerFs->mount(report, mapperName(), mountPoint))
0396         {
0397             m_isMounted = true;
0398 
0399             const QStorageInfo storageInfo = QStorageInfo(mountPoint);
0400             if (storageInfo.isValid() && !mountPoint.isEmpty())
0401                 setSectorsUsed( (storageInfo.bytesTotal() - storageInfo.bytesFree() + payloadOffset()) / sectorSize());
0402 
0403             return true;
0404         }
0405     }
0406     else {
0407         ExternalCommand mountCmd(
0408                 report,
0409                 QStringLiteral("mount"),
0410                 { QStringLiteral("--verbose"), mapperName(), mountPoint });
0411         if (mountCmd.run() && mountCmd.exitCode() == 0)
0412         {
0413             m_isMounted = true;
0414             return true;
0415         }
0416     }
0417     return false;
0418 }
0419 
0420 bool luks::unmount(Report& report, const QString& deviceNode)
0421 {
0422     if (!m_isCryptOpen)
0423     {
0424         qWarning() << "Cannot unmount device" << deviceNode
0425                    << "before decrypting it first.";
0426         return false;
0427     }
0428 
0429     if (!m_isMounted)
0430     {
0431         qWarning() << "Cannot unmount device" << deviceNode
0432                    << "because it's not mounted.";
0433         return false;
0434     }
0435 
0436     Q_ASSERT(m_innerFs);
0437 
0438     if (mapperName().isEmpty())
0439         return false;
0440 
0441     if (m_innerFs->canUnmount(mapperName()))
0442     {
0443         if (m_innerFs->unmount(report, mapperName()))
0444         {
0445             m_isMounted = false;
0446             return true;
0447         }
0448     }
0449     else {
0450         ExternalCommand unmountCmd( report,
0451                 QStringLiteral("umount"),
0452                 { QStringLiteral("--verbose"), QStringLiteral("--all-targets"), mapperName() });
0453         if (unmountCmd.run() && unmountCmd.exitCode() == 0)
0454         {
0455             m_isMounted = false;
0456             return true;
0457         }
0458     }
0459     return false;
0460 }
0461 
0462 FileSystem::Type luks::type() const
0463 {
0464     if (m_isCryptOpen && m_innerFs)
0465         return m_innerFs->type();
0466     return FileSystem::Type::Luks;
0467 }
0468 
0469 QString luks::suggestedMapperName(const QString& deviceNode) const
0470 {
0471     return QStringLiteral("luks-") + readOuterUUID(deviceNode);
0472 }
0473 
0474 QString luks::readLabel(const QString& deviceNode) const
0475 {
0476     if (m_isCryptOpen && m_innerFs)
0477         return m_innerFs->readLabel(mapperName());
0478 
0479     return FileSystem::readLabel(deviceNode);
0480 }
0481 
0482 bool luks::writeLabel(Report& report, const QString&, const QString& newLabel)
0483 {
0484     Q_ASSERT(m_innerFs);
0485     return m_innerFs->writeLabel(report, mapperName(), newLabel);
0486 }
0487 
0488 bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) const
0489 {
0490     Q_ASSERT(m_innerFs);
0491 
0492     if (mapperName().isEmpty())
0493         return false;
0494 
0495     const qint64 sizeDiff = newLength - length() * sectorSize();
0496     const qint64 newPayloadSize = m_PayloadSize + sizeDiff;
0497     if ( sizeDiff > 0 ) // grow
0498     {
0499         ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
0500         report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
0501 
0502         if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
0503             return m_innerFs->resize(report, mapperName(), newPayloadSize);
0504     }
0505     else if (m_innerFs->resize(report, mapperName(), newPayloadSize)) // shrink
0506     {
0507         ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"),
0508                 {  QStringLiteral("--size"), QString::number(newPayloadSize / 512), // LUKS1 payload length is specified in multiples of 512 bytes
0509                    QStringLiteral("resize"), mapperName() });
0510         report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
0511         if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
0512             return true;
0513     }
0514     report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition <filename>%1</filename> failed.", deviceNode);
0515     return false;
0516 }
0517 
0518 bool luks::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const
0519 {
0520     Q_UNUSED(mountPoint)
0521     return resize(report, deviceNode, length);
0522 }
0523 
0524 QString luks::readUUID(const QString& deviceNode) const
0525 {
0526     QString outerUuid = readOuterUUID(deviceNode);
0527     if (m_isCryptOpen && m_innerFs)
0528         return m_innerFs->readUUID(mapperName());
0529     return outerUuid;
0530 }
0531 
0532 QString luks::readOuterUUID(const QString &deviceNode) const
0533 {
0534     if ( deviceNode.isEmpty() )
0535         return QString();
0536 
0537     ExternalCommand cmd(QStringLiteral("cryptsetup"),
0538                         { QStringLiteral("luksUUID"), deviceNode });
0539     if (cmd.run()) {
0540         if ( cmd.exitCode() )
0541         {
0542             qWarning() << "Cannot get luksUUID for device" << deviceNode
0543                        << "\tcryptsetup exit code" << cmd.exitCode()
0544                        << "\toutput:" << cmd.output().trimmed();
0545             return QString();
0546         }
0547         QString outerUuid = cmd.output().trimmed();
0548         const_cast< QString& >( m_outerUuid ) = outerUuid;
0549         return outerUuid;
0550     }
0551     return QStringLiteral("---");
0552 }
0553 
0554 bool luks::updateUUID(Report& report, const QString& deviceNode) const
0555 {
0556     const QString uuid = QUuid::createUuid().toString().remove(QRegularExpression(QStringLiteral("\\{|\\}")));
0557 
0558     ExternalCommand cmd(report,
0559                         QStringLiteral("cryptsetup"),
0560                         { QStringLiteral("luksUUID"),
0561                           deviceNode,
0562                           QStringLiteral("--uuid"),
0563                           uuid });
0564     return cmd.run(-1) && cmd.exitCode() == 0;
0565 }
0566 
0567 void luks::getMapperName(const QString& deviceNode)
0568 {
0569     ExternalCommand cmd(QStringLiteral("lsblk"),
0570                         { QStringLiteral("--list"),
0571                           QStringLiteral("--noheadings"),
0572                           QStringLiteral("--paths"),
0573                           QStringLiteral("--json"),
0574                           QStringLiteral("--output"),
0575                           QStringLiteral("type,name"),
0576                           deviceNode });
0577     m_MapperName = QString();
0578 
0579     if (cmd.run(-1) && cmd.exitCode() == 0) {
0580         const QJsonDocument jsonDocument = QJsonDocument::fromJson(cmd.rawOutput());
0581         QJsonObject jsonObject = jsonDocument.object();
0582         const QJsonArray jsonArray = jsonObject[QLatin1String("blockdevices")].toArray();
0583         for (const auto &deviceLine : jsonArray) {
0584             QJsonObject deviceObject = deviceLine.toObject();
0585             if (deviceObject[QLatin1String("type")].toString() == QLatin1String("crypt")) {
0586                 m_MapperName = deviceObject[QLatin1String("name")].toString();
0587                 break;
0588             }
0589         }
0590     }
0591 }
0592 
0593 void luks::getLuksInfo(const QString& deviceNode)
0594 {
0595     ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode });
0596     if (cmd.run(-1) && cmd.exitCode() == 0) {
0597         QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)"));
0598         QRegularExpressionMatch rem = re.match(cmd.output());
0599         if (rem.hasMatch())
0600             m_CipherName = rem.captured(1);
0601         else
0602             m_CipherName = QLatin1String("---");
0603 
0604         re.setPattern(QStringLiteral("Cipher mode:\\s+(\\w+)"));
0605         rem = re.match(cmd.output());
0606         if (rem.hasMatch())
0607             m_CipherMode = rem.captured(1);
0608         else
0609             m_CipherMode = QLatin1String("---");
0610 
0611         re.setPattern(QStringLiteral("Hash spec:\\s+(\\w+)"));
0612         rem = re.match(cmd.output());
0613         if (rem.hasMatch())
0614             m_HashName = rem.captured(1);
0615         else
0616             m_HashName = QLatin1String("---");
0617 
0618         re.setPattern(QStringLiteral("MK bits:\\s+(\\d+)"));
0619         rem = re.match(cmd.output());
0620         if (rem.hasMatch())
0621             m_KeySize = rem.captured(1).toLongLong();
0622         else
0623             m_KeySize = -1;
0624 
0625         re.setPattern(QStringLiteral("Payload offset:\\s+(\\d+)"));
0626         rem = re.match(cmd.output());
0627         if (rem.hasMatch())
0628             m_PayloadOffset = rem.captured(1).toLongLong() * 512; // assuming LUKS sector size is 512;
0629         else
0630             m_PayloadOffset = -1;
0631 
0632     }
0633     else {
0634         m_CipherName = QLatin1String("---");
0635         m_CipherMode = QLatin1String("---");
0636         m_HashName = QLatin1String("---");
0637         m_KeySize = -1;
0638         m_PayloadOffset = -1;
0639     }
0640 }
0641 
0642 QString luks::outerUuid() const
0643 {
0644     return m_outerUuid;
0645 }
0646 
0647 bool luks::canEncryptType(FileSystem::Type type)
0648 {
0649     switch (type)
0650     {
0651         case Type::Btrfs:
0652         case Type::F2fs:
0653         case Type::Ext2:
0654         case Type::Ext3:
0655         case Type::Ext4:
0656         case Type::Jfs:
0657         case Type::LinuxSwap:
0658         case Type::Lvm2_PV:
0659         case Type::Nilfs2:
0660         case Type::ReiserFS:
0661         case Type::Reiser4:
0662         case Type::Xfs:
0663         case Type::Zfs:
0664             return true;
0665         default:
0666             return false;
0667     }
0668 }
0669 
0670 void luks::initLUKS()
0671 {
0672     setPayloadSize();
0673     QString mapperNode = mapperName();
0674     bool isCryptOpen = !mapperNode.isEmpty();
0675     setCryptOpen(isCryptOpen);
0676     if (isCryptOpen) {
0677         loadInnerFileSystem(mapperNode);
0678         setMounted(detectMountStatus(innerFS(), mapperNode));
0679     }
0680 }
0681 
0682 void luks::setPayloadSize()
0683 {
0684     ExternalCommand dmsetupCmd(QStringLiteral("dmsetup"), { QStringLiteral("table"), mapperName() });
0685     dmsetupCmd.run();
0686     QRegularExpression re(QStringLiteral("\\d+ (\\d+)"));
0687     QRegularExpressionMatch rem = re.match(dmsetupCmd.output());
0688     if (rem.hasMatch())
0689         m_PayloadSize = rem.captured(1).toLongLong() * sectorSize();
0690 }
0691 
0692 bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const {
0693     ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode });
0694     if (cmd.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.exitCode() == 0)
0695         return true;
0696 
0697     return false;
0698 }
0699 
0700 }