diff --git a/src/core/lvmdevice.cpp b/src/core/lvmdevice.cpp index 341dca5..4fa4308 100644 --- a/src/core/lvmdevice.cpp +++ b/src/core/lvmdevice.cpp @@ -1,222 +1,201 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * * * 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/lvmdevice.h" #include "fs/filesystem.h" #include "fs/filesystemfactory.h" #include "core/partition.h" #include "core/partitiontable.h" #include "util/externalcommand.h" #include #include /** Constructs a representation of LVM device with functionning LV as Partition @param name Volume Group name */ LvmDevice::LvmDevice(const QString& name, const QString& iconname) : VolumeManagerDevice(name, (QStringLiteral("/dev/") + name), getPeSize(name), getTotalPE(name), iconname, Device::LVM_Device) , m_peSize(getPeSize(name)) , m_totalPE(getTotalPE(name)) , m_allocPE(getAllocatedPE(name)) , m_freePE(getFreePE(name)) , m_UUID(getUUID(name)) { initPartitions(); } /* void LvmDevice::update() const { } */ void LvmDevice::initPartitions() { qint64 firstUsable = 0; qint64 lastusable = totalPE() - 1; PartitionTable* pTable = new PartitionTable(PartitionTable::vmd, firstUsable, lastusable); foreach (Partition* p, scanPartitions(*this, pTable)) { pTable->append(p); } - this->setPartitionTable(pTable); + setPartitionTable(pTable); } /** return sorted Partition(LV) Array */ QList LvmDevice::scanPartitions(const Device& dev, PartitionTable* pTable) const { QList pList; QList lvNodeList; ExternalCommand cmd(QStringLiteral("lvm"), { QStringLiteral("lvdisplay"), QStringLiteral("--units"), QStringLiteral("B"), dev.name()}); if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression pathRE(QStringLiteral("LV Path\\h+((\\w|\/)+)")); + QRegularExpression pathRE(QStringLiteral("LV Path\\h+((\\w|/)+)")); QRegularExpressionMatchIterator pathMatch = pathRE.globalMatch(cmd.output()); while (pathMatch.hasNext()) { QRegularExpressionMatch path = pathMatch.next(); lvNodeList << path.captured(1); } } foreach (QString lvNode, lvNodeList) { - pList.append(this->scanPartition(lvNode, dev, pTable)); + pList.append(scanPartition(lvNode, dev, pTable)); } return pList; } /** return sorted Partition(LV) Array */ Partition* LvmDevice::scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const { qint64 startSector; qint64 endSector; QString mountPoint = QString(); bool mounted = false; ExternalCommand cmd(QStringLiteral("lvm"), { QStringLiteral("lvdisplay"), QStringLiteral("--units"), QStringLiteral("B"), QStringLiteral("--maps"), lvPath}); if (cmd.run(-1) && cmd.exitCode() == 0) { //TODO: regex for first and last sector of the LV //TODO: stringing PE into one large contingiuous array of PE ?? QRegularExpression re(QStringLiteral("Physical extents\\h+(\\d+)\\sto\\s(\\d+)")); QRegularExpressionMatch match = re.match(cmd.output()); if (match.hasMatch()) { startSector = match.captured(1).toLongLong(); endSector = match.captured(2).toLongLong(); } } FileSystem* fs = FileSystemFactory::create(FileSystem::detectFileSystem(lvPath), startSector, endSector); Partition* part = new Partition(pTable, dev, PartitionRole(PartitionRole::Lvm_Lv), fs, startSector, endSector, lvPath, PartitionTable::Flag::FlagLvm, mountPoint, mounted); return part; } -qint32 LvmDevice::getPeSize(const QString& vgname) +QList LvmDevice::deviceNodeList() const { - ExternalCommand cmd(QStringLiteral("lvm"), - { QStringLiteral("vgdisplay"), - QStringLiteral("--units"), - QStringLiteral("B"), - vgname}); - if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression re(QStringLiteral("PE Size\\h+(\\d+)")); - QRegularExpressionMatch match = re.match(cmd.output()); - if (match.hasMatch()) { - return match.captured(1).toInt(); + QList devPathList; + QString cmdOutput = getField(QStringLiteral("pv_name"), name()); + + if (cmdOutput.size()) { + QList tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts); + foreach(QString devPath, tempPathList) { + devPathList.append(devPath.trimmed()); } } - return -1; + + return devPathList; +} + +qint32 LvmDevice::getPeSize(const QString& vgname) +{ + QString val = getField(QStringLiteral("vg_extent_size"), vgname); + return val.isEmpty() ? -1 : val.toInt(); } qint32 LvmDevice::getTotalPE(const QString& vgname) { - ExternalCommand cmd(QStringLiteral("lvm"), - { QStringLiteral("vgdisplay"), - QStringLiteral("--units"), - QStringLiteral("B"), - vgname}); - if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression re(QStringLiteral("Total PE\\h+(\\d+)")); - QRegularExpressionMatch match = re.match(cmd.output()); - if (match.hasMatch()) { - return match.captured(1).toInt(); - } - } - return -1; + QString val = getField(QStringLiteral("vg_extent_count"), vgname); + return val.isEmpty() ? -1 : val.toInt(); } qint32 LvmDevice::getAllocatedPE(const QString& vgname) { - ExternalCommand cmd(QStringLiteral("lvm"), - { QStringLiteral("vgdisplay"), - QStringLiteral("--units"), - QStringLiteral("B"), - vgname}); - if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression re(QStringLiteral("Alloc PE / Size\\h+(\\d+)")); - QRegularExpressionMatch match = re.match(cmd.output()); - if (match.hasMatch()) { - return match.captured(1).toInt(); - } - } - return -1; + return getTotalPE(vgname) - getFreePE(vgname); } qint32 LvmDevice::getFreePE(const QString& vgname) { - ExternalCommand cmd(QStringLiteral("lvm"), - { QStringLiteral("vgdisplay"), - QStringLiteral("--units"), - QStringLiteral("B"), - vgname}); - if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression re(QStringLiteral("Free PE / Size\\h+(\\d+)")); - QRegularExpressionMatch match = re.match(cmd.output()); - if (match.hasMatch()) { - return match.captured(1).toInt(); - } - } - return -1; + QString val = getField(QStringLiteral("vg_free_count"), vgname); + return val.isEmpty() ? -1 : val.toInt(); } QString LvmDevice::getUUID(const QString& vgname) +{ + QString val = getField(QStringLiteral("vg_uuid"), vgname); + return val.isEmpty() ? QStringLiteral("---") : val; + +} + +QString LvmDevice::getField(const QString& fieldName, const QString& vgname) { ExternalCommand cmd(QStringLiteral("lvm"), - { QStringLiteral("vgdisplay"), + { QStringLiteral("vgs"), + QStringLiteral("--foreign"), + QStringLiteral("--readonly"), + QStringLiteral("--noheadings"), QStringLiteral("--units"), QStringLiteral("B"), - vgname}); + QStringLiteral("--nosuffix"), + QStringLiteral("--options"), + fieldName, + vgname }); if (cmd.run(-1) && cmd.exitCode() == 0) { - QRegularExpression re(QStringLiteral("LV UUID\\h+(\\w+)")); - QRegularExpressionMatch match = re.match(cmd.output()); - if (match.hasMatch()) { - return match.captured(1); - } + return cmd.output().trimmed(); } - return QStringLiteral("---"); + return QString(); } diff --git a/src/core/lvmdevice.h b/src/core/lvmdevice.h index 8f28474..47ab17d 100644 --- a/src/core/lvmdevice.h +++ b/src/core/lvmdevice.h @@ -1,89 +1,91 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * * * 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(LVMDEVICE__H) #define LVMDEVICE__H #include "core/volumemanagerdevice.h" #include "util/libpartitionmanagerexport.h" #include #include #include class PartitionTable; class CreatePartitionTableOperation; class SmartStatus; /** A device. Represents a device like /dev/sda. Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. @see PartitionTable, Partition @author Volker Lanz */ class LIBKPMCORE_EXPORT LvmDevice : public VolumeManagerDevice { Q_DISABLE_COPY(LvmDevice) public: LvmDevice(const QString& name, const QString& iconname = QString()); public: QList scanPartitions(const Device& dev, PartitionTable* pTable) const; Partition* scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const; static qint32 getPeSize(const QString& name); static qint32 getTotalPE(const QString& name); static qint32 getAllocatedPE(const QString& name); static qint32 getFreePE(const QString& name); static QString getUUID(const QString& name); + static QString getField(const QString& fieldName, const QString& vgname = QString()); protected: void initPartitions(); + QList deviceNodeList() const override; public: qint32 peSize() const { return m_peSize; } qint32 totalPE() const { return m_totalPE; } qint32 allocatedPE() const { return m_allocPE; } qint32 freePE() const { return m_freePE; } QString UUID() const { return m_UUID; } private: qint32 m_peSize; qint32 m_totalPE; qint32 m_allocPE; qint32 m_freePE; QString m_UUID; }; #endif diff --git a/src/core/volumemanagerdevice.cpp b/src/core/volumemanagerdevice.cpp index 89136d1..255c692 100644 --- a/src/core/volumemanagerdevice.cpp +++ b/src/core/volumemanagerdevice.cpp @@ -1,36 +1,49 @@ /************************************************************************* * Copyright (C) 2008 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 "core/volumemanagerdevice.h" #include "core/partitiontable.h" #include "core/smartstatus.h" #include "util/capacity.h" /** Constructs a Device with an empty PartitionTable. */ VolumeManagerDevice::VolumeManagerDevice(const QString& name, const QString& devicenode, const qint32 logicalSize, const qint64 totalLogical, const QString& iconname, Device::Type type) : Device(name, devicenode, logicalSize, totalLogical, iconname, type) { } + +QString VolumeManagerDevice::prettyDeviceNodeList() const +{ + QString rval; + foreach (QString devNode, deviceNodeList()) { + rval += devNode + QStringLiteral(","); + } + + if (rval.size()) { + rval.chop(1); + } + return rval; +} diff --git a/src/core/volumemanagerdevice.h b/src/core/volumemanagerdevice.h index 5bdf0f7..da5764f 100644 --- a/src/core/volumemanagerdevice.h +++ b/src/core/volumemanagerdevice.h @@ -1,55 +1,59 @@ /************************************************************************* * 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(VOLUMEMANAGERDEVICE__H) #define VOLUMEMANAGERDEVICE__H #include "util/libpartitionmanagerexport.h" #include "core/device.h" #include #include #include class PartitionTable; class CreatePartitionTableOperation; class CoreBackend; class SmartStatus; class Partition; /** A device. Represents a device like /dev/sda. Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. @see PartitionTable, Partition @author Volker Lanz */ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device { Q_DISABLE_COPY(VolumeManagerDevice) protected: VolumeManagerDevice(const QString& name, const QString& devicenode, const qint32 logicalSize, const qint64 totalLogical, const QString& iconname = QString(), Device::Type type = Device::Unknown_Device); + virtual QList deviceNodeList() const = 0; /** Return list of physical device or partitions that makes up volumeManagerDevice */ public: //virtual void refresh() const = 0; /* VG infos can be changed, unlike disk_device */ //virtual Qlist listDevices() const = 0; + virtual QString prettyDeviceNodeList() const; + +private: }; #endif diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 7f43b57..869d871 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -1,133 +1,133 @@ /************************************************************************* * Copyright (C) 2008 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 "util/externalcommand.h" #include "util/report.h" #include #include #include #include /** 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) : QProcess(), m_Report(nullptr), m_Command(cmd), m_Args(args), m_ExitCode(-1), m_Output() { setup(); } /** Creates a new ExternalCommand instance with Report. @param report the Report to write output to. @param cmd the command to run @param args the arguments to pass to the command */ ExternalCommand::ExternalCommand(Report& report, const QString& cmd, const QStringList& args) : QProcess(), m_Report(report.newChild()), m_Command(cmd), m_Args(args), m_ExitCode(-1), m_Output() { setup(); } void ExternalCommand::setup() { - setEnvironment(QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("PATH=") + QString::fromUtf8(getenv("PATH"))); + setEnvironment(QStringList() << QStringLiteral("LC_ALL=C") << QStringLiteral("PATH=") + QString::fromUtf8(getenv("PATH")) << QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1")); setProcessChannelMode(MergedChannels); connect(this, static_cast(&QProcess::finished), this, &ExternalCommand::onFinished); connect(this, &ExternalCommand::readyReadStandardOutput, this, &ExternalCommand::onReadOutput); } /** Starts the external command. @param timeout timeout to wait for the process to start @return true on success */ bool ExternalCommand::start(int timeout) { QProcess::start(command(), args()); if (report()) { report()->setCommand(i18nc("@info/plain", "Command: %1 %2", command(), args().join(QStringLiteral(" ")))); } if (!waitForStarted(timeout)) { if (report()) report()->line() << i18nc("@info/plain", "(Command timeout while starting)"); return false; } 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() << i18nc("@info/plain", "(Command timeout while running)"); return false; } onReadOutput(); 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; } void ExternalCommand::onReadOutput() { const QString s = QString::fromUtf8(readAllStandardOutput()); m_Output += s; if (report()) *report() << s; } void ExternalCommand::onFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus) setExitCode(exitCode); }