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 @@ -1,494 +1,494 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * 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/lvmdevice.h" #include "core/partition.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/report.h" #include #include #include #include /** 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, (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(); initPartitions(); } /** * shared list of PV's paths that will be added to any VGs. * (have been added to an operation, but not yet applied) */ QVector LvmDevice::s_DirtyPVs; LvmDevice::~LvmDevice() { delete m_LVPathList; delete m_LVSizeMap; } void LvmDevice::initPartitions() { qint64 firstUsable = 0; 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); } pTable->updateUnallocated(*this); setPartitionTable(pTable); } /** * @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)); } return pList; } /** scan and construct a partition(LV) at a given path * * NOTE: * LVM partition has 2 different start and end sector values * 1. representing the actual LV start from 0 -> size of LV - 1 * 2. representing abstract LV's sector inside a VG partitionTable * start from last sector + 1 of last Partitions -> size of LV - 1 * Reason for this is for the LV Partition to work nicely with other parts of the codebase * without too many special cases. * * @param lvPath LVM Logical Volume path * @param pTable Abstract partition table representing partitions of LVM Volume Group * @return initialized Partition(LV) */ Partition* LvmDevice::scanPartition(const QString& lvPath, PartitionTable* pTable) const { activateLV(lvPath); qint64 lvSize = getTotalLE(lvPath); qint64 startSector = mappedSector(lvPath, 0); qint64 endSector = startSector + lvSize - 1; FileSystem::Type type = FileSystem::detectFileSystem(lvPath); FileSystem* fs = FileSystemFactory::create(type, 0, lvSize - 1, logicalSize()); fs->scan(lvPath); PartitionRole::Roles r = PartitionRole::Lvm_Lv; QString mountPoint; 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(); QString mapperNode = luksFs->mapperName(); mountPoint = FileSystem::detectMountPoint(fs, mapperNode); mounted = FileSystem::detectMountStatus(fs, mapperNode); } else { 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) fs->setSectorsUsed(qCeil(fs->readUsedCapacity(lvPath) / static_cast(logicalSize()))); } if (fs->supportGetLabel() != FileSystem::cmdSupportNone) { fs->setLabel(fs->readLabel(lvPath)); } if (fs->supportGetUUID() != FileSystem::cmdSupportNone) fs->setUUID(fs->readUUID(lvPath)); Partition* part = new Partition(pTable, *this, PartitionRole(r), fs, startSector, endSector, lvPath, PartitionTable::Flag::FlagNone, mountPoint, mounted); return part; } /** scan and construct list of initialized LvmDevice objects. * * @param devices list of initialized Devices */ void LvmDevice::scanSystemLVM(QList& devices) { QList lvmList; for (const auto &vgName : getVGs()) { 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); // 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())); } // Inform LvmDevice about which physical volumes form that particular LvmDevice for (const auto &d : lvmList) for (const auto &p : qAsConst(LVM::pvList)) if (p.vgName() == d->name()) d->physicalVolumes().append(p.partition()); } qint64 LvmDevice::mappedSector(const QString& lvPath, qint64 sector) const { qint64 mSector = 0; QStringList lvpathList = partitionNodes(); qint32 devIndex = lvpathList.indexOf(lvPath); if (devIndex) { for (int i = 0; i < devIndex; i++) { mSector += LVSizeMap()->value(lvpathList[i]); } mSector += sector; } return mSector; } const QStringList LvmDevice::deviceNodes() const { QStringList pvList; for (const auto &p : physicalVolumes()) { if (p->roles().has(PartitionRole::Luks)) pvList << static_cast(&p->fileSystem())->mapperName(); else pvList << p->partitionPath(); } return pvList; } const QStringList LvmDevice::partitionNodes() const { return *LVPathList(); } qint64 LvmDevice::partitionSize(QString& partitionPath) const { return LVSizeMap()->value(partitionPath); } const QStringList LvmDevice::getVGs() { QStringList vgList; QString output = getField(QStringLiteral("vg_name")); if (!output.isEmpty()) { const QStringList vgNameList = output.split(QStringLiteral("\n"), QString::SkipEmptyParts); for (const auto &vgName : vgNameList) { vgList.append(vgName.trimmed()); } } return vgList; } const QStringList LvmDevice::getLVs(const QString& vgName) { QStringList lvPathList; QString cmdOutput = getField(QStringLiteral("lv_path"), vgName); if (cmdOutput.size()) { const QStringList tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts); for (const auto &lvPath : tempPathList) { lvPathList.append(lvPath.trimmed()); } } return lvPathList; } qint64 LvmDevice::getPeSize(const QString& vgName) { QString val = getField(QStringLiteral("vg_extent_size"), vgName); return val.isEmpty() ? -1 : val.toLongLong(); } qint64 LvmDevice::getTotalPE(const QString& vgName) { QString val = getField(QStringLiteral("vg_extent_count"), vgName); return val.isEmpty() ? -1 : val.toInt(); } qint64 LvmDevice::getAllocatedPE(const QString& vgName) { return getTotalPE(vgName) - getFreePE(vgName); } qint64 LvmDevice::getFreePE(const QString& vgName) { 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; } /** Get LVM vgs command output with field name * * @param fieldName LVM field name * @param vgName the name of LVM Volume Group * @return raw output of command output, usually with many spaces within the returned string * */ QString LvmDevice::getField(const QString& fieldName, const QString& vgName) { QStringList args = { QStringLiteral("vgs"), QStringLiteral("--foreign"), QStringLiteral("--readonly"), QStringLiteral("--noheadings"), QStringLiteral("--units"), QStringLiteral("B"), QStringLiteral("--nosuffix"), QStringLiteral("--options"), fieldName }; if (!vgName.isEmpty()) { args << vgName; } ExternalCommand cmd(QStringLiteral("lvm"), args, QProcess::ProcessChannelMode::SeparateChannels); if (cmd.run(-1) && cmd.exitCode() == 0) { return cmd.output().trimmed(); } return QString(); } qint64 LvmDevice::getTotalLE(const QString& lvPath) { ExternalCommand cmd(QStringLiteral("lvm"), { QStringLiteral("lvdisplay"), lvPath}); if (cmd.run(-1) && cmd.exitCode() == 0) { QRegularExpression re(QStringLiteral("Current LE\\h+(\\d+)")); QRegularExpressionMatch match = re.match(cmd.output()); if (match.hasMatch()) { return match.captured(1).toInt(); } } return -1; } bool LvmDevice::removeLV(Report& report, LvmDevice& d, Partition& p) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvremove"), QStringLiteral("--yes"), p.partitionPath()}); if (cmd.run(-1) && cmd.exitCode() == 0) { d.partitionTable()->remove(&p); return true; } return false; } bool LvmDevice::createLV(Report& report, LvmDevice& d, Partition& p, const QString& lvName) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvcreate"), QStringLiteral("--yes"), QStringLiteral("--extents"), QString::number(p.length()), QStringLiteral("--name"), lvName, d.name()}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::createLVSnapshot(Report& report, Partition& p, const QString& name, const qint64 extents) { QString numExtents = (extents > 0) ? QString::number(extents) : QString::number(p.length()); ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvcreate"), QStringLiteral("--yes"), QStringLiteral("--extents"), numExtents, QStringLiteral("--snapshot"), QStringLiteral("--name"), name, p.partitionPath() }); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::resizeLV(Report& report, Partition& p) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("lvresize"), QStringLiteral("--force"), QStringLiteral("--yes"), QStringLiteral("--extents"), QString::number(p.length()), p.partitionPath()}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::removePV(Report& report, LvmDevice& d, const QString& pvPath) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgreduce"), d.name(), pvPath}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::insertPV(Report& report, LvmDevice& d, const QString& pvPath) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgextend"), QStringLiteral("--yes"), d.name(), pvPath}); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::movePV(Report& report, const QString& pvPath, const QStringList& destinations) { if (FS::lvm2_pv::getAllocatedPE(pvPath) <= 0) return true; QStringList args = QStringList(); args << QStringLiteral("pvmove"); args << pvPath; if (!destinations.isEmpty()) for (const auto &destPath : destinations) args << destPath.trimmed(); ExternalCommand cmd(report, QStringLiteral("lvm"), args); return (cmd.run(-1) && cmd.exitCode() == 0); } 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); args << vgName; for (const auto &p : pvList) { if (p->roles().has(PartitionRole::Luks)) args << static_cast(&p->fileSystem())->mapperName(); else args << p->partitionPath(); } ExternalCommand cmd(report, QStringLiteral("lvm"), args); return (cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::removeVG(Report& report, LvmDevice& d) { bool deactivated = deactivateVG(report, d); ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("vgremove"), QStringLiteral("--force"), d.name() }); return (deactivated && cmd.run(-1) && cmd.exitCode() == 0); } bool LvmDevice::deactivateVG(Report& report, const LvmDevice& d) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("vgchange"), QStringLiteral("--activate"), QStringLiteral("n"), d.name() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::deactivateLV(Report& report, const Partition& p) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("lvchange"), QStringLiteral("--activate"), QStringLiteral("n"), p.partitionPath() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::activateVG(Report& report, const LvmDevice& d) { ExternalCommand deactivate(report, QStringLiteral("lvm"), { QStringLiteral("vgchange"), QStringLiteral("--activate"), QStringLiteral("y"), d.name() }); return deactivate.run(-1) && deactivate.exitCode() == 0; } bool LvmDevice::activateLV(const QString& lvPath) { ExternalCommand deactivate(QStringLiteral("lvm"), { QStringLiteral("lvchange"), QStringLiteral("--activate"), QStringLiteral("y"), lvPath }); return deactivate.run(-1) && deactivate.exitCode() == 0; } 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 @@ -1,587 +1,587 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * Copyright (C) 2016 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 .* *************************************************************************/ /** @file */ #include "core/partitiontable.h" #include "core/partition.h" #include "core/device.h" #include "core/diskdevice.h" #include "core/lvmdevice.h" #include "core/partitionalignment.h" #include "fs/filesystem.h" #include "fs/filesystemfactory.h" #include "util/globallog.h" #include #include #include /** Creates a new PartitionTable object with type MSDOS @param type name of the PartitionTable type (e.g. "msdos" or "gpt") */ PartitionTable::PartitionTable(TableType type, qint64 firstUsable, qint64 lastUsable) : PartitionNode() , m_Children() , m_MaxPrimaries(maxPrimariesForTableType(type)) , m_Type(type) , m_FirstUsable(firstUsable) , m_LastUsable(lastUsable) { } /** Copy constructor for PartitionTable. * @param other the other PartitionTable. */ PartitionTable::PartitionTable(const PartitionTable& other) : PartitionNode() , m_Children() , m_MaxPrimaries(other.m_MaxPrimaries) , m_Type(other.m_Type) , m_FirstUsable(other.m_FirstUsable) , m_LastUsable(other.m_LastUsable) { for (Partitions::const_iterator it = other.m_Children.constBegin(); it != other.m_Children.constEnd(); ++it) { m_Children.append(new Partition(**it, this)); } } /** Destroys a PartitionTable object, destroying all children */ PartitionTable::~PartitionTable() { clearChildren(); } /** Gets the number of free sectors before a given child Partition in this PartitionTable. @param p the Partition for which to get the free sectors before @returns the number of free sectors before the Partition */ qint64 PartitionTable::freeSectorsBefore(const Partition& p) const { const Partition* pred = predecessor(p); // due to the space required for extended boot records the // below is NOT the same as pred->length() if (pred && pred->roles().has(PartitionRole::Unallocated)) return p.firstSector() - pred->firstSector(); return 0; } /** Gets the number of free sectors after a given child Partition in this PartitionTable. @param p the Partition for which to get the free sectors after @returns the number of free sectors after the Partition */ qint64 PartitionTable::freeSectorsAfter(const Partition& p) const { const Partition* succ = successor(p); // due to the space required for extended boot records the // below is NOT the same as succ->length() if (succ && succ->roles().has(PartitionRole::Unallocated)) return succ->lastSector() - p.lastSector(); return 0; } qint64 PartitionTable::freeSectors() const { qint64 sectors = 0; for (const auto &p : children()) { if (p->roles().has(PartitionRole::Unallocated)) { sectors += p->length(); } } return sectors; } /** @return true if the PartitionTable has an extended Partition */ bool PartitionTable::hasExtended() const { for (const auto &p : children()) if (p->roles().has(PartitionRole::Extended)) return true; return false; } /** @return pointer to the PartitionTable's extended Partition or nullptr if none exists */ Partition* PartitionTable::extended() const { for (const auto &p : children()) if (p->roles().has(PartitionRole::Extended)) return p; return nullptr; } /** Gets valid PartitionRoles for a Partition @param p the Partition @return valid roles for the given Partition */ PartitionRole::Roles PartitionTable::childRoles(const Partition& p) const { Q_ASSERT(p.parent()); PartitionRole::Roles r = p.parent()->isRoot() ? PartitionRole::Primary : PartitionRole::Logical; if (r == PartitionRole::Primary && hasExtended() == false && tableTypeSupportsExtended(type())) r |= PartitionRole::Extended; return r; } /** @return the number of primaries in this PartitionTable */ int PartitionTable::numPrimaries() const { int result = 0; for (const auto &p : children()) if (p->roles().has(PartitionRole::Primary) || p->roles().has(PartitionRole::Extended)) result++; return result; } /** Appends a Partition to this PartitionTable @param partition pointer of the partition to append. Must not be nullptr. */ void PartitionTable::append(Partition* partition) { children().append(partition); std::sort(children().begin(), children().end(), [] (const Partition *a, const Partition *b) -> bool {return a->firstSector() < b->firstSector();}); } /** @param f the flag to get the name for @returns the flags name or an empty QString if the flag is not known */ QString PartitionTable::flagName(Flag f) { switch (f) { case PartitionTable::FlagBoot: return xi18nc("@item partition flag", "boot"); case PartitionTable::FlagRoot: return xi18nc("@item partition flag", "root"); case PartitionTable::FlagSwap: return xi18nc("@item partition flag", "swap"); case PartitionTable::FlagHidden: return xi18nc("@item partition flag", "hidden"); case PartitionTable::FlagRaid: return xi18nc("@item partition flag", "raid"); case PartitionTable::FlagLvm: return xi18nc("@item partition flag", "lvm"); case PartitionTable::FlagLba: return xi18nc("@item partition flag", "lba"); case PartitionTable::FlagHpService: return xi18nc("@item partition flag", "hpservice"); case PartitionTable::FlagPalo: return xi18nc("@item partition flag", "palo"); case PartitionTable::FlagPrep: return xi18nc("@item partition flag", "prep"); case PartitionTable::FlagMsftReserved: return xi18nc("@item partition flag", "msft-reserved"); case PartitionTable::FlagBiosGrub: return xi18nc("@item partition flag", "bios-grub"); case PartitionTable::FlagAppleTvRecovery: return xi18nc("@item partition flag", "apple-tv-recovery"); case PartitionTable::FlagDiag: return xi18nc("@item partition flag", "diag"); case PartitionTable::FlagLegacyBoot: return xi18nc("@item partition flag", "legacy-boot"); case PartitionTable::FlagMsftData: return xi18nc("@item partition flag", "msft-data"); case PartitionTable::FlagIrst: return xi18nc("@item partition flag", "irst"); case PartitionTable::FlagEsp: return xi18nc("@item partition flag", "esp"); default: break; } return QString(); } /** @return list of all flags */ const QList PartitionTable::flagList() { QList rval; rval.append(PartitionTable::FlagBoot); rval.append(PartitionTable::FlagRoot); rval.append(PartitionTable::FlagSwap); rval.append(PartitionTable::FlagHidden); rval.append(PartitionTable::FlagRaid); rval.append(PartitionTable::FlagLvm); rval.append(PartitionTable::FlagLba); rval.append(PartitionTable::FlagHpService); rval.append(PartitionTable::FlagPalo); rval.append(PartitionTable::FlagPrep); rval.append(PartitionTable::FlagMsftReserved); rval.append(PartitionTable::FlagBiosGrub); rval.append(PartitionTable::FlagAppleTvRecovery); rval.append(PartitionTable::FlagDiag); rval.append(PartitionTable::FlagLegacyBoot); rval.append(PartitionTable::FlagMsftData); rval.append(PartitionTable::FlagIrst); rval.append(PartitionTable::FlagEsp); return rval; } /** @param flags the flags to get the names for @returns QStringList of the flags' names */ QStringList PartitionTable::flagNames(Flags flags) { QStringList rval; int f = 1; QString s; while (!(s = flagName(static_cast(f))).isEmpty()) { if (flags & f) rval.append(s); f <<= 1; } return rval; } bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent, qint64& start, qint64& end) { if (d.type() == Device::Disk_Device) { const DiskDevice& device = dynamic_cast(d); if (!parent.isRoot()) { Partition* extended = dynamic_cast(&parent); if (extended == nullptr) { qWarning() << "extended is null. start: " << start << ", end: " << end << ", device: " << device.deviceNode(); return false; } // Leave a track (cylinder aligned) or sector alignment sectors (sector based) free at the // start for a new partition's metadata start += device.partitionTable()->type() == PartitionTable::msdos ? device.sectorsPerTrack() : PartitionAlignment::sectorAlignment(device); // .. and also at the end for the metadata for a partition to follow us, if we're not // at the end of the extended partition if (end < extended->lastSector()) end -= device.partitionTable()->type() == PartitionTable::msdos ? device.sectorsPerTrack() : PartitionAlignment::sectorAlignment(device); } return end - start + 1 >= PartitionAlignment::sectorAlignment(device); } else if (d.type() == Device::LVM_Device) { if (end - start + 1 > 0) { return true; } } return false; } /** Creates a new unallocated Partition on the given Device. @param device the Device to create the new Partition on @param parent the parent PartitionNode for the new Partition @param start the new Partition's start sector @param end the new Partition's end sector @return pointer to the newly created Partition object or nullptr if the Partition could not be created */ Partition* createUnallocated(const Device& device, PartitionNode& parent, qint64 start, qint64 end) { PartitionRole::Roles r = PartitionRole::Unallocated; if (!parent.isRoot()) 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) r |= PartitionRole::Lvm_Lv; 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 @param p pointer to the parent to remove unallocated children from */ void PartitionTable::removeUnallocated(PartitionNode* p) { Q_ASSERT(p); qint32 i = 0; while (i < p->children().size()) { Partition* child = p->children()[i]; if (child->roles().has(PartitionRole::Unallocated)) { p->remove(child); delete child; continue; } if (child->roles().has(PartitionRole::Extended)) removeUnallocated(child); i++; } } /** @overload */ void PartitionTable::removeUnallocated() { removeUnallocated(this); } /** Inserts unallocated children for a Device's PartitionTable with the given parent. This method inserts unallocated Partitions for a parent, usually the Device this PartitionTable is on. It will also insert unallocated Partitions in any extended Partitions it finds. @warning This method assumes that no unallocated Partitions exist when it is called. @param d the Device this PartitionTable and @p p are on @param p the parent PartitionNode (may be this or an extended Partition) @param start the first sector to begin looking for free space */ void PartitionTable::insertUnallocated(const Device& d, PartitionNode* p, qint64 start) { Q_ASSERT(p); qint64 lastEnd = start; if (d.type() == Device::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(); }); for (const auto &child : children()) { qint64 totalSectors = child->length(); child->setFirstSector(lastEnd); child->setLastSector(lastEnd + totalSectors - 1); lastEnd += totalSectors; } } else { const auto pChildren = p->children(); for (const auto &child : pChildren) { p->insert(createUnallocated(d, *p, lastEnd, child->firstSector() - 1)); if (child->roles().has(PartitionRole::Extended)) insertUnallocated(d, child, child->firstSector()); lastEnd = child->lastSector() + 1; } } // 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 (parentEnd >= firstUsable() && parentEnd >= lastEnd) p->insert(createUnallocated(d, *p, lastEnd, parentEnd)); } /** Updates the unallocated Partitions for this PartitionTable. @param d the Device this PartitionTable is on */ void PartitionTable::updateUnallocated(const Device& d) { removeUnallocated(); insertUnallocated(d, this, firstUsable()); } qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t) { Q_UNUSED(t) if (d.type() == Device::LVM_Device) { return 0; } const DiskDevice& diskDevice = dynamic_cast(d); return PartitionAlignment::sectorAlignment(diskDevice); } qint64 PartitionTable::defaultLastUsable(const Device& d, TableType t) { if (t == gpt) return d.totalLogical() - 1 - 32 - 1; return d.totalLogical() - 1; } static struct { const QLatin1String name; /**< name of partition table type */ quint32 maxPrimaries; /**< max numbers of primary partitions supported */ bool canHaveExtended; /**< does partition table type support extended partitions */ bool isReadOnly; /**< does KDE Partition Manager support this only in read only mode */ PartitionTable::TableType type; /**< enum type */ } tableTypes[] = { { QLatin1String("aix"), 4, false, true, PartitionTable::aix }, { QLatin1String("bsd"), 8, false, true, PartitionTable::bsd }, { QLatin1String("dasd"), 1, false, true, PartitionTable::dasd }, { QLatin1String("msdos"), 4, true, false, PartitionTable::msdos }, { QLatin1String("msdos"), 4, true, false, PartitionTable::msdos_sectorbased }, { QLatin1String("dos"), 4, true, false, PartitionTable::msdos_sectorbased }, { QLatin1String("dvh"), 16, true, true, PartitionTable::dvh }, { QLatin1String("gpt"), 128, false, false, PartitionTable::gpt }, { QLatin1String("loop"), 1, false, true, PartitionTable::loop }, { QLatin1String("mac"), 0xffff, false, true, PartitionTable::mac }, { QLatin1String("pc98"), 16, false, true, PartitionTable::pc98 }, { QLatin1String("amiga"), 128, false, true, PartitionTable::amiga }, { QLatin1String("sun"), 8, false, true, PartitionTable::sun }, { QLatin1String("vmd"), 0xffff, false, false, PartitionTable::vmd } }; PartitionTable::TableType PartitionTable::nameToTableType(const QString& n) { for (const auto &type : tableTypes) if (n == type.name) return type.type; return PartitionTable::unknownTableType; } QString PartitionTable::tableTypeToName(TableType l) { for (const auto &type : tableTypes) if (l == type.type) return type.name; return xi18nc("@item partition table name", "unknown"); } qint32 PartitionTable::maxPrimariesForTableType(TableType l) { for (const auto &type : tableTypes) if (l == type.type) return type.maxPrimaries; return 1; } bool PartitionTable::tableTypeSupportsExtended(TableType l) { for (const auto &type : tableTypes) if (l == type.type) return type.canHaveExtended; return false; } bool PartitionTable::tableTypeIsReadOnly(TableType l) { for (const auto &type : tableTypes) if (l == type.type) return type.isReadOnly; return false; } /** Simple heuristic to determine if the PartitionTable is sector aligned (i.e. if its Partitions begin at sectors evenly divisable by PartitionAlignment::sectorAlignment(). @return true if is sector aligned, otherwise false */ bool PartitionTable::isSectorBased(const Device& d) const { if (d.type() == Device::Disk_Device) { const DiskDevice& diskDevice = dynamic_cast(d); if (type() == PartitionTable::msdos) { // the default for empty partition tables is sector based if (numPrimaries() == 0) return true; quint32 numCylinderAligned = 0; quint32 numSectorAligned = 0; // see if we have more cylinder aligned partitions than sector // aligned ones. for (const auto &p : children()) { if (p->firstSector() % PartitionAlignment::sectorAlignment(diskDevice) == 0) numSectorAligned++; else if (p->firstSector() % diskDevice.cylinderSize() == 0) numCylinderAligned++; } return numSectorAligned >= numCylinderAligned; } return type() == PartitionTable::msdos_sectorbased; } return false; } void PartitionTable::setType(const Device& d, TableType t) { setFirstUsableSector(defaultFirstUsable(d, t)); setLastUsableSector(defaultLastUsable(d, t)); m_Type = t; updateUnallocated(d); } QTextStream& operator<<(QTextStream& stream, const PartitionTable& ptable) { stream << "type: \"" << ptable.typeName() << "\"\n" << "align: \"" << (ptable.type() == PartitionTable::msdos ? "cylinder" : "sector") << "\"\n" << "\n# number start end type roles label flags\n"; QList partitions; for (const auto &p : ptable.children()) { if (!p->roles().has(PartitionRole::Unallocated)) { partitions.append(p); if (p->roles().has(PartitionRole::Extended)) { const auto partChildren = p->children(); for (const auto &child : partChildren) { if (!child->roles().has(PartitionRole::Unallocated)) partitions.append(child); } } } } std::sort(partitions.begin(), partitions.end(), [](const Partition* p1, const Partition* p2) { return p1->number() < p2->number(); }); for (const auto &p : qAsConst(partitions)) stream << *p; return stream; } 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 @@ -1,120 +1,120 @@ /************************************************************************* * Copyright (C) 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 "fs/exfat.h" #include "util/externalcommand.h" #include "util/capacity.h" #include namespace FS { FileSystem::CommandSupportType exfat::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType exfat::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void exfat::init() { m_Create = findExternal(QStringLiteral("mkfs.exfat")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("exfatfsck"), QStringList(), 1) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_SetLabel = findExternal(QStringLiteral("exfatlabel")) ? cmdSupportFileSystem : cmdSupportNone; m_UpdateUUID = cmdSupportNone; m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool exfat::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool exfat::supportToolName() const { return SupportTool(QStringLiteral("exfat-utils"), QUrl(QStringLiteral("http://code.google.com/p/exfat/"))); } qint64 exfat::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } int exfat::maxLabelLength() const { return 15; } bool exfat::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("exfatfsck"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool exfat::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.exfat"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool exfat::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("exfatlabel"), { deviceNode, newLabel }); return cmd.run(-1) && cmd.exitCode() == 0; } bool exfat::updateUUID(Report& report, const QString& deviceNode) const { Q_UNUSED(report); Q_UNUSED(deviceNode); return false; } } 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 @@ -1,114 +1,114 @@ /************************************************************************* * Copyright (C) 2008,2009 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_EXT2_H) #define KPMCORE_EXT2_H #include "util/libpartitionmanagerexport.h" #include "fs/filesystem.h" #include class Report; class QString; namespace FS { /** An ext2 file system. @author Volker Lanz */ 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; qint64 readUsedCapacity(const QString& deviceNode) const override; bool check(Report& report, const QString& deviceNode) const override; bool create(Report& report, const QString& deviceNode) override; bool resize(Report& report, const QString& deviceNode, qint64 length) const override; bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override; bool writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) override; bool updateUUID(Report& report, const QString& deviceNode) const override; CommandSupportType supportGetUsed() const override { return m_GetUsed; } CommandSupportType supportGetLabel() const override { return m_GetLabel; } CommandSupportType supportCreate() const override { return m_Create; } CommandSupportType supportGrow() const override { return m_Grow; } CommandSupportType supportShrink() const override { return m_Shrink; } CommandSupportType supportMove() const override { return m_Move; } CommandSupportType supportCheck() const override { return m_Check; } CommandSupportType supportCopy() const override { return m_Copy; } CommandSupportType supportBackup() const override { return m_Backup; } CommandSupportType supportSetLabel() const override { return m_SetLabel; } CommandSupportType supportSetLabelOnline() const override { return m_SetLabel; } CommandSupportType supportUpdateUUID() const override { return m_UpdateUUID; } CommandSupportType supportGetUUID() const override { return m_GetUUID; } qint64 maxCapacity() const override; int maxLabelLength() const override; SupportTool supportToolName() const override; bool supportToolFound() const override; public: static CommandSupportType m_GetUsed; static CommandSupportType m_GetLabel; static CommandSupportType m_Create; static CommandSupportType m_Grow; static CommandSupportType m_Shrink; static CommandSupportType m_Move; static CommandSupportType m_Check; static CommandSupportType m_Copy; static CommandSupportType m_Backup; static CommandSupportType m_SetLabel; static CommandSupportType m_UpdateUUID; static CommandSupportType m_GetUUID; }; } #endif 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 @@ -1,47 +1,47 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/ext3.h" #include "util/externalcommand.h" #include "util/capacity.h" #include 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) { } qint64 ext3::maxCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } bool ext3::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.ext3"), QStringList() << QStringLiteral("-qF") << deviceNode); return cmd.run(-1) && cmd.exitCode() == 0; } bool ext3::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const { return resize(report, deviceNode, length); } } 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 @@ -1,47 +1,47 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/ext4.h" #include "util/externalcommand.h" #include "util/capacity.h" #include 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) { } qint64 ext4::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } bool ext4::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.ext4"), QStringList() << QStringLiteral("-qF") << deviceNode); return cmd.run(-1) && cmd.exitCode() == 0; } bool ext4::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const { return resize(report, deviceNode, length); } } 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 @@ -1,37 +1,37 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/extended.h" namespace FS { FileSystem::CommandSupportType extended::m_Create = FileSystem::cmdSupportFileSystem; FileSystem::CommandSupportType extended::m_Grow = FileSystem::cmdSupportCore; 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) { } bool extended::create(Report&, const QString&) { return true; } } 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 @@ -1,145 +1,145 @@ /************************************************************************* * 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 "fs/f2fs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include #include namespace FS { FileSystem::CommandSupportType f2fs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_SetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType f2fs::m_UpdateUUID = FileSystem::cmdSupportNone; 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) { } void f2fs::init() { m_Create = findExternal(QStringLiteral("mkfs.f2fs")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("fsck.f2fs")) ? cmdSupportFileSystem : cmdSupportNone; if (m_Create == cmdSupportFileSystem) { ExternalCommand cmd(QStringLiteral("mkfs.f2fs"), {}); oldVersion = cmd.run(-1) && !cmd.output().contains(QStringLiteral("-f")); } m_GetLabel = cmdSupportCore; // m_SetLabel = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; // m_UpdateUUID = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = (m_Check != cmdSupportNone && findExternal(QStringLiteral("resize.f2fs"))) ? cmdSupportFileSystem : cmdSupportNone; // m_GetUsed = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; // m_Shrink = (m_Grow != cmdSupportNone && m_GetUsed != cmdSupportNone) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool f2fs::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && // m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool f2fs::supportToolName() const { return SupportTool(QStringLiteral("f2fs-tools"), QUrl(QStringLiteral("https://git.kernel.org/cgit/linux/kernel/git/jaegeuk/f2fs-tools.git"))); } qint64 f2fs::minCapacity() const { return 30 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 f2fs::maxCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); } int f2fs::maxLabelLength() const { return 80; } bool f2fs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.f2fs"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool f2fs::create(Report& report, const QString& deviceNode) { return createWithLabel(report, deviceNode, QString()); } bool f2fs::createWithLabel(Report& report, const QString& deviceNode, const QString& label) { QStringList args; if (oldVersion) args << QStringLiteral("-l") << label << deviceNode; else args << QStringLiteral("-f") << QStringLiteral("-l") << label << deviceNode; ExternalCommand cmd(report, QStringLiteral("mkfs.f2fs"), args); return cmd.run(-1) && cmd.exitCode() == 0; } bool f2fs::resize(Report& report, const QString& deviceNode, qint64 length) const { Q_UNUSED(length) ExternalCommand cmd(report, QStringLiteral("resize.f2fs"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,112 +1,112 @@ /************************************************************************* * Copyright (C) 2008,2009 by Volker Lanz * * 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 .* *************************************************************************/ #if !defined(KPMCORE_FAT12_H) #define KPMCORE_FAT12_H #include "util/libpartitionmanagerexport.h" #include "fs/filesystem.h" #include class Report; class QString; namespace FS { /** A fat12 file system. @author Andrius Štikonas */ 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; qint64 readUsedCapacity(const QString& deviceNode) const override; bool check(Report& report, const QString& deviceNode) const override; bool create(Report& report, const QString& deviceNode) override; bool updateUUID(Report& report, const QString& deviceNode) const override; bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override; CommandSupportType supportGetUsed() const override { return m_GetUsed; } CommandSupportType supportGetLabel() const override { return m_GetLabel; } CommandSupportType supportSetLabel() const override { return m_SetLabel; } CommandSupportType supportCreate() const override { return m_Create; } CommandSupportType supportGrow() const override { return m_Grow; } CommandSupportType supportShrink() const override { return m_Shrink; } CommandSupportType supportMove() const override { return m_Move; } CommandSupportType supportCheck() const override { return m_Check; } CommandSupportType supportCopy() const override { return m_Copy; } CommandSupportType supportBackup() const override { return m_Backup; } CommandSupportType supportUpdateUUID() const override { return m_UpdateUUID; } CommandSupportType supportGetUUID() const override { return m_GetUUID; } qint64 minCapacity() const override; qint64 maxCapacity() const override; int maxLabelLength() const override; QValidator* labelValidator(QObject *parent) const override; SupportTool supportToolName() const override; bool supportToolFound() const override; public: static CommandSupportType m_GetUsed; static CommandSupportType m_GetLabel; static CommandSupportType m_SetLabel; static CommandSupportType m_Create; static CommandSupportType m_Grow; static CommandSupportType m_Shrink; static CommandSupportType m_Move; static CommandSupportType m_Check; static CommandSupportType m_Copy; static CommandSupportType m_Backup; static CommandSupportType m_UpdateUUID; static CommandSupportType m_GetUUID; }; } #endif 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 @@ -1,98 +1,98 @@ /************************************************************************* * Copyright (C) 2008,2009,2011 by Volker Lanz * * 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 .* *************************************************************************/ #include "fs/fat16.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include #include 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) { } fat16::fat16(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type type) : fat12(firstsector, lastsector, sectorsused, label, type) { } void fat16::init() { m_Create = m_GetUsed = m_Check = findExternal(QStringLiteral("mkfs.fat"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_SetLabel = findExternal(QStringLiteral("fatlabel")) ? cmdSupportFileSystem : cmdSupportNone; m_Move = cmdSupportCore; m_Copy = cmdSupportCore; m_Backup = cmdSupportCore; m_UpdateUUID = findExternal(QStringLiteral("dd")) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = findExternal(QStringLiteral("fatresize")) ? cmdSupportFileSystem : cmdSupportNone; m_Shrink = findExternal(QStringLiteral("fatresize")) ? cmdSupportFileSystem : cmdSupportNone; m_GetUUID = cmdSupportCore; } bool fat16::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } qint64 fat16::minCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 fat16::maxCapacity() const { return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::GiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } bool fat16::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.fat"), { QStringLiteral("-F16"), QStringLiteral("-I"), QStringLiteral("-v"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool fat16::resize(Report& report, const QString& deviceNode, qint64 length) const { ExternalCommand cmd(report, QStringLiteral("fatresize"), { QStringLiteral("--verbose"), QStringLiteral("--size"), QString::number(length), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,70 +1,70 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/fat32.h" #include "util/externalcommand.h" #include "util/capacity.h" #include #include 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) { } qint64 fat32::minCapacity() const { return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 fat32::maxCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } bool fat32::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.fat"), { QStringLiteral("-F32"), QStringLiteral("-I"), QStringLiteral("-v"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool fat32::updateUUID(Report& report, const QString& deviceNode) const { qint64 t = time(nullptr); char uuid[4]; for (auto &u : uuid) { u = static_cast(t & 0xff); t >>= 8; } // HACK: replace this hack with fatlabel "-i" (dosfstools 4.2) ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") }); if (!cmd.write(QByteArray(uuid, sizeof(uuid)))) return false; if (!cmd.start()) return false; return cmd.waitFor(-1); } } 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 @@ -1,555 +1,554 @@ /************************************************************************* * Copyright (C) 2012 by Volker Lanz * * Copyright (C) 2015 by Teo Mrnjavac * * 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/fstab.h" #include "fs/filesystem.h" #include "fs/lvm2_pv.h" #include "backend/corebackend.h" #include "backend/corebackendmanager.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/helpers.h" #include #include #include #include #include const std::vector FileSystem::defaultColorCode = { { QColor( 220,205,175 ), // unknown QColor( 187,249,207 ), // extended QColor( 102,121,150 ), // ext2 QColor( 122,145,180 ), // ext3 QColor( 143,170,210 ), // ext4 QColor( 155,155,130 ), // swap QColor( 204,179,215 ), // fat16 QColor( 229,201,240 ), // fat32 QColor( 244,214,255 ), // ntfs QColor( 216,220,135 ), // reiser QColor( 251,255,157 ), // reiser4 QColor( 200,255,254 ), // xfs QColor( 137,200,198 ), // jfs QColor( 210,136,142 ), // hfs QColor( 240,165,171 ), // hfs+ QColor( 151,220,134 ), // ufs QColor( 220,205,175 ), // unformatted QColor( 173,205,255 ), // btrfs QColor( 176,155,185 ), // hpfs QColor( 170,30,77 ), // luks QColor( 96,140,85 ), // ocfs2 QColor( 33,137,108 ), // zfs QColor( 250,230,255 ), // exfat QColor( 242,155,104 ), // nilfs2 QColor( 160,210,180 ), // lvm2 pv QColor( 255,170,0 ), // f2fs QColor( 170,120,255 ), // udf QColor( 177,82,69 ), // iso9660 QColor( 223,39,104 ), // luks2 QColor( 204,179,255 ) // fat12 } }; /** 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 */ 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() { } /** Reads the capacity in use on this FileSystem @param deviceNode the device node for the Partition the FileSystem is on @return the used capacity in bytes or -1 in case of an error */ qint64 FileSystem::readUsedCapacity(const QString& deviceNode) const { Q_UNUSED(deviceNode) return -1; } FileSystem::Type FileSystem::detectFileSystem(const QString& partitionPath) { return CoreBackendManager::self()->backend()->detectFileSystem(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 return QString(); QStringList mountPoints; QFileInfo partitionPathFileInfo(partitionPath); QString partitionCanonicalPath = partitionPathFileInfo.canonicalFilePath(); const QList mountedVolumes = QStorageInfo::mountedVolumes(); for (const QStorageInfo &storage : mountedVolumes) { if (partitionCanonicalPath == QFileInfo(QString::fromLocal8Bit(storage.device())).canonicalFilePath() ) { mountPoints.append(storage.rootPath()); } } mountPoints.append(possibleMountPoints(partitionPath)); return mountPoints.isEmpty() ? QString() : mountPoints.first(); } 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); } return mounted; } /** Reads the label for this FileSystem @param deviceNode the device node for the Partition the FileSystem is on @return the FileSystem label or an empty string in case of error */ QString FileSystem::readLabel(const QString& deviceNode) const { return CoreBackendManager::self()->backend()->readLabel(deviceNode); } /** Creates a new FileSystem @param report Report to write status information to @param deviceNode the device node for the Partition to create the FileSystem on @return true if successful */ bool FileSystem::create(Report& report, const QString& deviceNode) { Q_UNUSED(report) Q_UNUSED(deviceNode) return true; } /** Creates a new FileSystem with a specified Label @param report Report to write status information to @param deviceNode the device node for the Partition to create the FileSystem on @param label the new label for the FileSystem @return true if successful */ bool FileSystem::createWithLabel(Report& report, const QString& deviceNode, const QString& label) { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(label) 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 @param newLength the new length for the FileSystem in bytes @return true on success */ bool FileSystem::resize(Report& report, const QString& deviceNode, qint64 newLength) const { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(newLength) return true; } /** Resize a mounted 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 @param mountPoint the mount point where FileSystem is mounted on @param newLength the new length for the FileSystem in bytes @return true on success */ bool FileSystem::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 newLength) const { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(mountPoint) Q_UNUSED(newLength) 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 @param newStartSector the new start sector for the FileSystem @return true on success */ bool FileSystem::move(Report& report, const QString& deviceNode, qint64 newStartSector) const { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(newStartSector) return true; } /** Writes a label for the FileSystem to disk @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @param newLabel the new label for the FileSystem @return true on success */ bool FileSystem::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(newLabel) return true; } /** Writes a label for the FileSystem to disk @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @param mountPoint the mount point where FileSystem is mounted on @param newLabel the new label for the FileSystem @return true on success */ bool FileSystem::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(mountPoint) Q_UNUSED(newLabel) return true; } /** Copies a FileSystem from one Partition to another @param report Report to write status information to @param targetDeviceNode device node of the target Partition @param sourceDeviceNode device node of the source Partition @return true on success */ bool FileSystem::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const { Q_UNUSED(report) Q_UNUSED(targetDeviceNode) Q_UNUSED(sourceDeviceNode) return true; } /** Backs up a FileSystem to a file @param report Report to write status information to @param sourceDevice Device the source FileSystem is on @param deviceNode device node of the source Partition @param filename name of the file to backup to @return true on success */ bool FileSystem::backup(Report& report, const Device& sourceDevice, const QString& deviceNode, const QString& filename) const { Q_UNUSED(report) Q_UNUSED(sourceDevice) Q_UNUSED(deviceNode) Q_UNUSED(filename) return false; } /** Removes a FileSystem @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @return true if FileSystem is removed */ bool FileSystem::remove(Report& report, const QString& deviceNode) const { Q_UNUSED(report) Q_UNUSED(deviceNode) return true; } /** Checks a FileSystem for errors @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @return true if FileSystem is error-free */ bool FileSystem::check(Report& report, const QString& deviceNode) const { Q_UNUSED(report) Q_UNUSED(deviceNode) return true; } /** Updates a FileSystem UUID on disk @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @return true on success */ bool FileSystem::updateUUID(Report& report, const QString& deviceNode) const { Q_UNUSED(report) Q_UNUSED(deviceNode) return true; } /** Returns the FileSystem UUID by calling a FileSystem-specific helper program @param deviceNode the device node for the Partition the FileSystem is on @return the UUID or an empty string if the FileSystem does not support UUIDs */ QString FileSystem::readUUID(const QString& deviceNode) const { return CoreBackendManager::self()->backend()->readUUID(deviceNode); } /** Give implementations of FileSystem a chance to update the boot sector after the file system has been moved or copied. @param report Report to write status information to @param deviceNode the device node for the Partition the FileSystem is on @return true on success */ bool FileSystem::updateBootSector(Report& report, const QString& deviceNode) const { Q_UNUSED(report) Q_UNUSED(deviceNode) return true; } /** @return the minimum capacity valid for this FileSystem in bytes */ qint64 FileSystem::minCapacity() const { return 8 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } /** @return the maximum capacity valid for this FileSystem in bytes */ qint64 FileSystem::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } /** @return the maximum label length valid for this FileSystem */ int FileSystem::maxLabelLength() const { return 16; } /** Validates the label for this FileSystem * @param parent the parent widget passed to the QObject constructor * @return QValidator to validate the file system label line edit input */ QValidator* FileSystem::labelValidator(QObject *parent) const { Q_UNUSED(parent) return nullptr; } /** @return this FileSystem's type as printable name */ QString FileSystem::name(const QStringList& languages) const { return nameForType(type(), languages); } /** @return a pointer to a QString C array with all FileSystem names */ static const KLocalizedString* typeNames() { static const KLocalizedString s[] = { kxi18nc("@item filesystem name", "unknown"), kxi18nc("@item filesystem name", "extended"), kxi18nc("@item filesystem name", "ext2"), kxi18nc("@item filesystem name", "ext3"), kxi18nc("@item filesystem name", "ext4"), kxi18nc("@item filesystem name", "linuxswap"), kxi18nc("@item filesystem name", "fat16"), kxi18nc("@item filesystem name", "fat32"), kxi18nc("@item filesystem name", "ntfs"), kxi18nc("@item filesystem name", "reiser"), kxi18nc("@item filesystem name", "reiser4"), kxi18nc("@item filesystem name", "xfs"), kxi18nc("@item filesystem name", "jfs"), kxi18nc("@item filesystem name", "hfs"), kxi18nc("@item filesystem name", "hfsplus"), kxi18nc("@item filesystem name", "ufs"), kxi18nc("@item filesystem name", "unformatted"), kxi18nc("@item filesystem name", "btrfs"), kxi18nc("@item filesystem name", "hpfs"), kxi18nc("@item filesystem name", "luks"), kxi18nc("@item filesystem name", "ocfs2"), kxi18nc("@item filesystem name", "zfs"), kxi18nc("@item filesystem name", "exfat"), kxi18nc("@item filesystem name", "nilfs2"), kxi18nc("@item filesystem name", "lvm2 pv"), kxi18nc("@item filesystem name", "f2fs"), kxi18nc("@item filesystem name", "udf"), kxi18nc("@item filesystem name", "iso9660"), kxi18nc("@item filesystem name", "luks2"), kxi18nc("@item filesystem name", "fat12") }; return s; } /** @param t the type to get the name for @return the printable name for the given type */ 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 @return the type for the name or FileSystem::Unknown if not found */ 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 */ 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; } /** @return printable menu title for mounting this FileSystem */ QString FileSystem::mountTitle() const { return xi18nc("@title:menu", "Mount"); } /** @return printable menu title for unmounting this FileSystem */ QString FileSystem::unmountTitle() const { return xi18nc("@title:menu", "Unmount"); } /** Moves a FileSystem to a new start sector. @param newStartSector where the FileSystem should be moved to */ void FileSystem::move(qint64 newStartSector) { const qint64 savedLength = length(); setFirstSector(newStartSector); setLastSector(newStartSector + savedLength - 1); } bool FileSystem::canMount(const QString& deviceNode, const QString& mountPoint) const { Q_UNUSED(deviceNode) // cannot mount if we have no mount points return !mountPoint.isEmpty(); } /** Attempt to mount this FileSystem on a given mount point @param report the report to write information to @param deviceNode the path to the device that is to be unmounted @param mountPoint the mount point to mount the FileSystem on @return true on success */ bool FileSystem::mount(Report& report, const QString &deviceNode, const QString &mountPoint) { ExternalCommand mountCmd( report, QStringLiteral("mount"), { QStringLiteral("--verbose"), deviceNode, mountPoint }); if (mountCmd.run() && mountCmd.exitCode() == 0) { return true; } return false; } /** Attempt to unmount this FileSystem @param report the report to write information to @param deviceNode the path to the device that is to be unmounted @return true on success */ bool FileSystem::unmount(Report& report, const QString& deviceNode) { ExternalCommand umountCmd( report, QStringLiteral("umount"), { QStringLiteral("--verbose"), QStringLiteral("--all-targets"), deviceNode }); if ( umountCmd.run() && umountCmd.exitCode() == 0 ) return true; return false; } bool FileSystem::findExternal(const QString& cmdName, const QStringList& args, int expectedCode) { QString cmdFullPath = QStandardPaths::findExecutable(cmdName); if (cmdFullPath.isEmpty()) cmdFullPath = QStandardPaths::findExecutable(cmdName, { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); ExternalCommand cmd(cmdFullPath, args); if (!cmd.run()) return false; return cmd.exitCode() == 0 || cmd.exitCode() == expectedCode; } bool FileSystem::supportToolFound() const { return false; } FileSystem::SupportTool FileSystem::supportToolName() const { return SupportTool(); } 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,297 +1,297 @@ /************************************************************************* * 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 * * 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_FILESYSTEM_H) +#ifndef KPMCORE_FILESYSTEM_H #define KPMCORE_FILESYSTEM_H #include "util/libpartitionmanagerexport.h" #include #include #include #include #include #include class QColor; class QValidator; class Device; class Report; /** Base class for all FileSystems. Represents a file system and handles support for various types of operations that can be performed on those. @author Volker Lanz */ class LIBKPMCORE_EXPORT FileSystem { Q_DISABLE_COPY(FileSystem) public: class SupportTool { public: explicit SupportTool(const QString& n = QString(), const QUrl& u = QUrl()) : name(n), url(u) {} const QString name; const QUrl url; }; /** Supported FileSystem types */ enum Type : int { - Unknown = 0, - Extended = 1, - - 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, - - __lastType = 30 + Unknown, + Extended, + + 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 }; /** The type of support for a given FileSystem action */ enum CommandSupportType { cmdSupportNone = 0, /**< no support */ cmdSupportCore = 1, /**< internal support */ cmdSupportFileSystem = 2, /**< supported by some external command */ cmdSupportBackend = 4 /**< supported by the backend */ }; static const std::vector defaultColorCode; Q_DECLARE_FLAGS(CommandSupportTypes, CommandSupportType) protected: FileSystem(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t); public: virtual ~FileSystem() {} 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); virtual bool createWithLabel(Report& report, const QString& deviceNode, const QString& label); virtual bool resize(Report& report, const QString& deviceNode, qint64 newLength) const; virtual bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 newLength) const; virtual bool move(Report& report, const QString& deviceNode, qint64 newStartSector) const; virtual bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel); virtual bool writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel); virtual bool copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const; virtual bool backup(Report& report, const Device& sourceDevice, const QString& deviceNode, const QString& filename) const; virtual bool remove(Report& report, const QString& deviceNode) const; virtual bool check(Report& report, const QString& deviceNode) const; virtual bool updateUUID(Report& report, const QString& deviceNode) const; virtual QString readUUID(const QString& deviceNode) const; virtual bool updateBootSector(Report& report, const QString& deviceNode) const; virtual CommandSupportType supportGetUsed() const { return cmdSupportNone; /**< @return CommandSupportType for getting used capacity */ } virtual CommandSupportType supportGetLabel() const { return cmdSupportNone; /**< @return CommandSupportType for reading label*/ } virtual CommandSupportType supportCreate() const { return cmdSupportNone; /**< @return CommandSupportType for creating */ } virtual CommandSupportType supportCreateWithLabel() const { return cmdSupportNone; /**< @return CommandSupportType for creating */ } virtual CommandSupportType supportGrow() const { return cmdSupportNone; /**< @return CommandSupportType for growing */ } virtual CommandSupportType supportGrowOnline() const { return cmdSupportNone; /**< @return CommandSupportType for online growing */ } virtual CommandSupportType supportShrink() const { return cmdSupportNone; /**< @return CommandSupportType for shrinking */ } virtual CommandSupportType supportShrinkOnline() const { return cmdSupportNone; /**< @return CommandSupportType for shrinking */ } virtual CommandSupportType supportMove() const { return cmdSupportNone; /**< @return CommandSupportType for moving */ } virtual CommandSupportType supportCheck() const { return cmdSupportNone; /**< @return CommandSupportType for checking */ } virtual CommandSupportType supportCheckOnline() const { return cmdSupportNone; /**< @return CommandSupportType for checking */ } virtual CommandSupportType supportCopy() const { return cmdSupportNone; /**< @return CommandSupportType for copying */ } virtual CommandSupportType supportBackup() const { return cmdSupportNone; /**< @return CommandSupportType for backing up */ } virtual CommandSupportType supportSetLabel() const { return cmdSupportNone; /**< @return CommandSupportType for setting label */ } virtual CommandSupportType supportSetLabelOnline() const { return cmdSupportNone; /**< @return CommandSupportType for setting label of mounted file systems */ } virtual CommandSupportType supportUpdateUUID() const { return cmdSupportNone; /**< @return CommandSupportType for updating the UUID */ } virtual CommandSupportType supportGetUUID() const { return cmdSupportNone; /**< @return CommandSupportType for reading the UUID */ } virtual qint64 minCapacity() const; virtual qint64 maxCapacity() const; virtual int maxLabelLength() const; virtual QValidator* labelValidator(QObject *parent = nullptr) const; virtual SupportTool supportToolName() const; virtual bool supportToolFound() const; /** * Returns the (possibly translated) name of the type of this filesystem. * @see nameForType() */ virtual QString name(const QStringList& languages = {}) const; virtual FileSystem::Type type() const { return m_Type; /**< @return the FileSystem's type */ } /** * Returns the name of the given filesystem type. If @p languages * is an empty list, uses the translated name of the filesystem, * in the default locale. If languages is {"C"}, an untranslated * string is returned. Passing other lists of language identifiers * may yield unpredicatable results -- see the documentation of * KLocalizedString() for details on the way toString() is used. * Returns a single QString with the name. */ static QString nameForType(FileSystem::Type t, const QStringList& languages = {}); static QList types(); static FileSystem::Type typeForName(const QString& s, const QStringList& languages = {}); static FileSystem::Type detectFileSystem(const QString& partitionPath); static QString detectMountPoint(FileSystem* fs, const QString& partitionPath); static bool detectMountStatus(FileSystem* fs, const QString& partitionPath); /**< @return true if this FileSystem can be mounted */ virtual bool canMount(const QString& deviceNode, const QString& mountPoint) const; virtual bool canUnmount(const QString&) const { return true; /**< @return true if this FileSystem can be unmounted */ } virtual QString mountTitle() const; virtual QString unmountTitle() const; 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 */ } qint64 length() const { return lastSector() - firstSector() + 1; /**< @return the FileSystem's length */ } qint64 firstByte() const { return firstSector() * sectorSize(); /**< @return the FileSystem's first byte */ } qint64 lastByte() const { 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 */ } 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 */ } 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 */ } 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; }; Q_DECLARE_OPERATORS_FOR_FLAGS(FileSystem::CommandSupportTypes) #endif 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 @@ -1,177 +1,177 @@ /************************************************************************* * Copyright (C) 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 "fs/filesystemfactory.h" #include "fs/filesystem.h" #include "fs/btrfs.h" #include "fs/exfat.h" #include "fs/ext2.h" #include "fs/ext3.h" #include "fs/ext4.h" #include "fs/extended.h" #include "fs/f2fs.h" #include "fs/fat12.h" #include "fs/fat16.h" #include "fs/fat32.h" #include "fs/hfs.h" #include "fs/hfsplus.h" #include "fs/hpfs.h" #include "fs/iso9660.h" #include "fs/jfs.h" #include "fs/linuxswap.h" #include "fs/luks.h" #include "fs/luks2.h" #include "fs/lvm2_pv.h" #include "fs/nilfs2.h" #include "fs/ntfs.h" #include "fs/ocfs2.h" #include "fs/reiser4.h" #include "fs/reiserfs.h" #include "fs/udf.h" #include "fs/ufs.h" #include "fs/unformatted.h" #include "fs/unknown.h" #include "fs/xfs.h" #include "fs/zfs.h" #include "backend/corebackendmanager.h" #include "backend/corebackend.h" FileSystemFactory::FileSystems FileSystemFactory::m_FileSystems; /** Initializes the instance. */ 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(); CoreBackendManager::self()->backend()->initFSSupport(); } /** Creates a new FileSystem @param t the FileSystem's type @param firstsector the FileSystem's first sector relative to the Device @param lastsector the FileSystem's last sector relative to the Device @param sectorsused the number of used sectors in the FileSystem @param label the FileSystem's label @return pointer to the newly created FileSystem object or nullptr if FileSystem could not be created */ FileSystem* FileSystemFactory::create(FileSystem::Type t, qint64 firstsector, qint64 lastsector, qint64 sectorSize, qint64 sectorsused, const QString& label, const QString& uuid) { 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; } if (fs != nullptr) { fs->setUUID(uuid); fs->setSectorSize(sectorSize); } return fs; } /** @overload */ FileSystem* FileSystemFactory::create(const FileSystem& other) { return create(other.type(), other.firstSector(), other.lastSector(), other.sectorSize(), other.sectorsUsed(), other.label(), other.uuid()); } /** @return the map of FileSystems */ const FileSystemFactory::FileSystems& FileSystemFactory::map() { return m_FileSystems; } /** Clones a FileSystem from another one, but with a new type. @param newType the new FileSystem's type @param other the old FileSystem to clone @return pointer to the newly created FileSystem or nullptr in case of errors */ FileSystem* FileSystemFactory::cloneWithNewType(FileSystem::Type newType, const FileSystem& other) { return create(newType, other.firstSector(), other.lastSector(), other.sectorSize(), other.sectorsUsed(), other.label()); } 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 @@ -1,54 +1,53 @@ /************************************************************************* * Copyright (C) 2008 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_FILESYSTEMFACTORY_H) - +#ifndef KPMCORE_FILESYSTEMFACTORY_H #define KPMCORE_FILESYSTEMFACTORY_H #include "fs/filesystem.h" #include "util/libpartitionmanagerexport.h" #include #include class QString; /** Factory to create instances of FileSystem. @author Volker Lanz */ class LIBKPMCORE_EXPORT FileSystemFactory { public: /** map of FileSystem::Types to pointers of FileSystem */ typedef QMap FileSystems; private: FileSystemFactory(); public: static void init(); static FileSystem* create(FileSystem::Type t, qint64 firstsector, qint64 lastsector, qint64 sectorSize, qint64 sectorsused = -1, const QString& label = QString(), const QString& uuid = QString()); static FileSystem* create(const FileSystem& other); static FileSystem* cloneWithNewType(FileSystem::Type newType, const FileSystem& other); static const FileSystems& map(); private: static FileSystems m_FileSystems; }; #endif 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 @@ -1,95 +1,95 @@ /************************************************************************* * Copyright (C) 2008,2011 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 "fs/hfs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include namespace FS { FileSystem::CommandSupportType hfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfs::m_Check = FileSystem::cmdSupportNone; 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) { } void hfs::init() { m_GetLabel = cmdSupportCore; m_Create = findExternal(QStringLiteral("hformat")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("hfsck")) ? cmdSupportFileSystem : cmdSupportNone; m_Move = m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Backup = cmdSupportCore; } bool hfs::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && // m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone; // m_GetUUID != cmdSupportNone; } FileSystem::SupportTool hfs::supportToolName() const { return SupportTool(QStringLiteral("hfsutils"), QUrl(QStringLiteral("http://www.mars.org/home/rob/proj/hfs/"))); } qint64 hfs::maxCapacity() const { return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); } int hfs::maxLabelLength() const { return 27; } bool hfs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("hfsck"), { QStringLiteral("-v"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool hfs::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("hformat"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,96 +1,96 @@ /************************************************************************* * Copyright (C) 2008,2011 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 "fs/hfsplus.h" #include "util/externalcommand.h" #include "util/capacity.h" #include namespace FS { FileSystem::CommandSupportType hfsplus::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hfsplus::m_Create = FileSystem::cmdSupportNone; 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) { } void hfsplus::init() { m_Check = findExternal(QStringLiteral("fsck_hfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("newfs_hfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Backup = cmdSupportCore; m_GetLabel = cmdSupportCore; } bool hfsplus::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && // m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone; // m_GetUUID != cmdSupportNone; } FileSystem::SupportTool hfsplus::supportToolName() const { return SupportTool(QStringLiteral("diskdev_cmds"), QUrl(QStringLiteral("http://opendarwin.org"))); } qint64 hfsplus::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } int hfsplus::maxLabelLength() const { return 63; } bool hfsplus::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.hfsplus"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool hfsplus::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.hfsplus"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,48 +1,48 @@ /************************************************************************* * 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 .* *************************************************************************/ #include "fs/hpfs.h" #include "util/capacity.h" #include namespace FS { FileSystem::CommandSupportType hpfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType hpfs::m_SetLabel = FileSystem::cmdSupportNone; 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) { } qint64 hpfs::maxCapacity() const { return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); } } 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 @@ -1,28 +1,28 @@ /************************************************************************* * 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 "fs/iso9660.h" 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 @@ -1,199 +1,199 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/jfs.h" #include "util/externalcommand.h" #include "util/report.h" #include "util/capacity.h" #include #include #include #include namespace FS { FileSystem::CommandSupportType jfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType jfs::m_Copy = FileSystem::cmdSupportNone; 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) { } void jfs::init() { m_GetUsed = findExternal(QStringLiteral("jfs_debugfs")) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_SetLabel = findExternal(QStringLiteral("jfs_tune"), { QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkfs.jfs"),{ QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = m_Check = findExternal(QStringLiteral("fsck.jfs"), { QStringLiteral("-V") }) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Backup = cmdSupportCore; } bool jfs::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone; // m_GetUUID != cmdSupportNone; } FileSystem::SupportTool jfs::supportToolName() const { return SupportTool(QStringLiteral("jfsutils"), QUrl(QStringLiteral("http://jfs.sourceforge.net/"))); } qint64 jfs::minCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 jfs::maxCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); } int jfs::maxLabelLength() const { return 11; } qint64 jfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("jfs_debugfs"), QStringList() << deviceNode); if (cmd.write(QByteArrayLiteral("dm")) && cmd.start() && cmd.waitFor()) { qint64 blockSize = -1; QRegularExpression re(QStringLiteral("Block Size: (\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); if (reBlockSize.hasMatch()) blockSize = reBlockSize.captured(1).toLongLong(); qint64 nBlocks = -1; re.setPattern(QStringLiteral("dn_mapsize:\\s+0x(\\x+)")); QRegularExpressionMatch renBlocks = re.match(cmd.output()); bool ok = false; if (renBlocks.hasMatch()) { nBlocks = renBlocks.captured(1).toLongLong(&ok, 16); if (!ok) nBlocks = -1; } qint64 nFree = -1; re.setPattern(QStringLiteral("dn_nfree:\\s+0x(\\x+)")); QRegularExpressionMatch renFree = re.match(cmd.output()); if (renFree.hasMatch()) { nFree = renFree.captured(1).toLongLong(&ok, 16); if (!ok) nFree = -1; } if (nBlocks > -1 && blockSize > -1 && nFree > -1) return (nBlocks - nFree) * blockSize; } return -1; } bool jfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("jfs_tune"), { QStringLiteral("-L"), newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool jfs::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) { Q_UNUSED(mountPoint) return writeLabel(report, deviceNode, newLabel); } bool jfs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.jfs"), { QStringLiteral("-f"), deviceNode }); return cmd.run(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 1); } bool jfs::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.jfs"), { QStringLiteral("-q"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool jfs::resize(Report& report, const QString& deviceNode, qint64) const { QTemporaryDir tempDir; if (!tempDir.isValid()) { report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition %1 failed: Could not create temp dir.", deviceNode); return false; } bool rval = false; ExternalCommand mountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), deviceNode, tempDir.path() }); if (mountCmd.run(-1)) { ExternalCommand resizeMountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), QStringLiteral("--options"), QStringLiteral("remount,resize"), deviceNode, tempDir.path() }); if (resizeMountCmd.run(-1) && resizeMountCmd.exitCode() == 0) rval = true; else report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition %1 failed: Remount failed.", deviceNode); ExternalCommand unmountCmd(report, QStringLiteral("umount"), { tempDir.path() }); if (!unmountCmd.run(-1)) report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition %1: Unmount failed.", deviceNode); } else report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition %1 failed: Initial mount failed.", deviceNode); return rval; } bool jfs::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64) const { ExternalCommand resizeMountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--type"), QStringLiteral("jfs"), QStringLiteral("--options"), QStringLiteral("remount,resize"), deviceNode, mountPoint }); if (resizeMountCmd.run(-1) && resizeMountCmd.exitCode() == 0) return true; report.line() << xi18nc("@info:progress", "Resizing JFS file system on partition %1 failed: Remount failed.", deviceNode); return false; } } 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 @@ -1,197 +1,197 @@ /************************************************************************* * Copyright (C) 2008,2009 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 "fs/linuxswap.h" #include "util/externalcommand.h" #include #include #include #include namespace FS { FileSystem::CommandSupportType linuxswap::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType linuxswap::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void linuxswap::init() { m_SetLabel = m_Shrink = m_Grow = m_Create = m_UpdateUUID = (findExternal(QStringLiteral("mkswap"))) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_GetUsed = cmdSupportFileSystem; m_Copy = cmdSupportFileSystem; m_Move = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool linuxswap::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && // m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && // m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool linuxswap::supportToolName() const { return SupportTool(QStringLiteral("util-linux"), QUrl(QStringLiteral("http://www.kernel.org/pub/linux/utils/util-linux-ng/"))); } int linuxswap::maxLabelLength() const { return 15; } bool linuxswap::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkswap"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::resize(Report& report, const QString& deviceNode, qint64 length) const { Q_UNUSED(length); const QString label = readLabel(deviceNode); const QString uuid = readUUID(deviceNode); QStringList args; if (!label.isEmpty()) args << QStringLiteral("--label") << label; if (!uuid.isEmpty()) args << QStringLiteral("--uuid") << uuid; args << deviceNode; ExternalCommand cmd(report, QStringLiteral("mkswap"), args); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const { const QString label = readLabel(sourceDeviceNode); const QString uuid = readUUID(sourceDeviceNode); QStringList args; if (!label.isEmpty()) args << QStringLiteral("--label") << label; if (!uuid.isEmpty()) args << QStringLiteral("--uuid") << uuid; args << targetDeviceNode; ExternalCommand cmd(report, QStringLiteral("mkswap"), args); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("swaplabel"), { QStringLiteral("--label"), newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::writeLabelOnline(Report& report, const QString& deviceNode, const QString& mountPoint, const QString& newLabel) { Q_UNUSED(mountPoint) return writeLabel(report, deviceNode, newLabel); } QString linuxswap::mountTitle() const { return xi18nc("@title:menu", "Activate swap"); } QString linuxswap::unmountTitle() const { return xi18nc("@title:menu", "Deactivate swap"); } bool linuxswap::canMount(const QString& deviceNode, const QString& mountPoint) const { 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); ExternalCommand cmd(report, QStringLiteral("swapon"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::unmount(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("swapoff"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool linuxswap::updateUUID(Report& report, const QString& deviceNode) const { const QString label = readLabel(deviceNode); QStringList args; if (!label.isEmpty()) args << QStringLiteral("--label") << label; args << deviceNode; ExternalCommand cmd(report, QStringLiteral("mkswap"), args); return cmd.run(-1) && cmd.exitCode() == 0; } qint64 linuxswap::readUsedCapacity(const QString& deviceNode) const { QFile swapsFile(QStringLiteral("/proc/swaps")); if (swapsFile.open(QIODevice::ReadOnly)) { QByteArray data = swapsFile.readAll(); swapsFile.close(); QTextStream in(&data); while (!in.atEnd()) { QStringList line = in.readLine().split(QRegularExpression(QStringLiteral("\\s+"))); QFileInfo kernelPath(deviceNode); if (line[0] == kernelPath.canonicalFilePath()) return line[3].toLongLong() * 1024; } } return -1; } } 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 @@ -1,700 +1,700 @@ /************************************************************************* * Copyright (C) 2012 by Volker Lanz * * Copyright (C) 2013-2017 by Andrius Štikonas * * Copyright (C) 2015-2016 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 .* *************************************************************************/ #include "fs/luks.h" #include "fs/lvm2_pv.h" #include "fs/filesystemfactory.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/helpers.h" #include "util/report.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace FS { FileSystem::CommandSupportType luks::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_SetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_UpdateUUID = FileSystem::cmdSupportNone; FileSystem::CommandSupportType luks::m_GetUUID = FileSystem::cmdSupportNone; luks::luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t) : FileSystem(firstsector, lastsector, sectorsused, label, t) , m_innerFs(nullptr) , m_isCryptOpen(false) , m_cryptsetupFound(m_Create != cmdSupportNone) , m_isMounted(false) , m_KeySize(-1) , m_PayloadOffset(-1) { } luks::~luks() { delete m_innerFs; } void luks::init() { CommandSupportType cryptsetupFound = findExternal(QStringLiteral("cryptsetup")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = cryptsetupFound; m_UpdateUUID = cryptsetupFound; m_GetUUID = cryptsetupFound; m_Grow = cryptsetupFound; m_Shrink = cryptsetupFound; m_SetLabel = cmdSupportNone; m_GetLabel = cmdSupportFileSystem; m_Check = cmdSupportCore; m_Copy = cmdSupportCore; m_Move = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUsed = cmdSupportNone; // libparted does not support LUKS, we do this as a special case } void luks::scan(const QString& deviceNode) { getMapperName(deviceNode); getLuksInfo(deviceNode); } bool luks::supportToolFound() const { return m_cryptsetupFound && ((m_isCryptOpen && m_innerFs) ? m_innerFs->supportToolFound() : true); } FileSystem::SupportTool luks::supportToolName() const { if (m_isCryptOpen && m_innerFs && m_cryptsetupFound) return m_innerFs->supportToolName(); return SupportTool(QStringLiteral("cryptsetup"), QUrl(QStringLiteral("https://code.google.com/p/cryptsetup/"))); } bool luks::create(Report& report, const QString& deviceNode) { Q_ASSERT(m_innerFs); Q_ASSERT(!m_passphrase.isEmpty()); ExternalCommand createCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("-s"), QStringLiteral("512"), QStringLiteral("--batch-mode"), QStringLiteral("--force-password"), QStringLiteral("--type"), QStringLiteral("luks1"), QStringLiteral("luksFormat"), deviceNode }); if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && createCmd.start(-1) && createCmd.waitFor() && createCmd.exitCode() == 0)) { return false; } ExternalCommand openCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("open"), deviceNode, suggestedMapperName(deviceNode) }); if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) return false; setPayloadSize(); scan(deviceNode); if (mapperName().isEmpty()) return false; if (!m_innerFs->create(report, mapperName())) return false; return true; } QString luks::mountTitle() const { return xi18nc("@title:menu", "Mount"); } QString luks::unmountTitle() const { return xi18nc("@title:menu", "Unmount"); } QString luks::cryptOpenTitle() const { return xi18nc("@title:menu", "Decrypt"); } QString luks::cryptCloseTitle() const { return xi18nc("@title:menu", "Deactivate"); } void luks::setPassphrase(const QString& passphrase) { m_passphrase = passphrase; } QString luks::passphrase() const { return m_passphrase; } bool luks::canMount(const QString&, const QString& mountPoint) const { return m_isCryptOpen && !m_isMounted && m_innerFs && m_innerFs->canMount(mapperName(), mountPoint); } bool luks::canUnmount(const QString&) const { return m_isCryptOpen && m_isMounted && m_innerFs && m_innerFs->canUnmount(mapperName()); } bool luks::isMounted() const { return m_isCryptOpen && m_isMounted; } void luks::setMounted(bool mounted) { m_isMounted = mounted; } bool luks::canCryptOpen(const QString&) const { return !m_isCryptOpen && !m_isMounted && supportToolFound(); } bool luks::canCryptClose(const QString&) const { return m_isCryptOpen && !m_isMounted && m_cryptsetupFound; } bool luks::isCryptOpen() const { return m_isCryptOpen; } void luks::setCryptOpen(bool cryptOpen) { m_isCryptOpen = cryptOpen; } bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) { if (m_isCryptOpen) { if (!mapperName().isEmpty()) { qWarning() << "LUKS device" << deviceNode << "already decrypted." << "Cannot decrypt again."; return false; } else { qWarning() << "LUKS device" << deviceNode << "reportedly decrypted but mapper node not found." << "Marking device as NOT decrypted and trying to " "decrypt again anyway."; m_isCryptOpen = false; } } KPasswordDialog dlg( parent ); dlg.setPrompt(i18n("Enter passphrase for %1:", deviceNode)); if( !dlg.exec() ) return false; QString passphrase = dlg.password(); ExternalCommand openCmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), deviceNode, suggestedMapperName(deviceNode) }); if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor() && openCmd.exitCode() == 0) ) return false; if (m_innerFs) { delete m_innerFs; m_innerFs = nullptr; } scan(deviceNode); if (mapperName().isEmpty()) return false; loadInnerFileSystem(mapperName()); m_isCryptOpen = (m_innerFs != nullptr); if (!m_isCryptOpen) 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; return true; } bool luks::cryptClose(const QString& deviceNode) { if (!m_isCryptOpen) { qWarning() << "Cannot close LUKS device" << deviceNode << "because it's not open."; return false; } if (m_isMounted) { qWarning() << "Cannot close LUKS device" << deviceNode << "because the filesystem is mounted."; return false; } ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("close"), mapperName() }); if (!(cmd.run(-1) && cmd.exitCode() == 0)) return false; delete m_innerFs; m_innerFs = nullptr; m_passphrase.clear(); setLabel(FileSystem::readLabel(deviceNode)); setUUID(readUUID(deviceNode)); setSectorsUsed(-1); m_isCryptOpen = (m_innerFs != nullptr); for (auto &p : LVM::pvList) if (!p.isLuks() && p.partition()->deviceNode() == deviceNode) p.setLuks(true); return true; } void luks::loadInnerFileSystem(const QString& mapperNode) { Q_ASSERT(!m_innerFs); FileSystem::Type innerFsType = detectFileSystem(mapperNode); m_innerFs = FileSystemFactory::cloneWithNewType(innerFsType, *this); setLabel(m_innerFs->readLabel(mapperNode)); setUUID(m_innerFs->readUUID(mapperNode)); if (m_innerFs->supportGetUsed() == FileSystem::cmdSupportFileSystem) setSectorsUsed(static_cast(std::ceil((m_innerFs->readUsedCapacity(mapperNode) + payloadOffset()) / static_cast(sectorSize()) ))); m_innerFs->scan(mapperNode); } void luks::createInnerFileSystem(FileSystem::Type type) { Q_ASSERT(!m_innerFs); m_innerFs = FileSystemFactory::cloneWithNewType(type, *this); } bool luks::check(Report& report, const QString&) const { Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; return m_innerFs->check(report, mapperName()); } qint64 luks::readUsedCapacity(const QString& deviceNode) const { if (!m_isCryptOpen) return -1; if (m_innerFs) return m_innerFs->readUsedCapacity(deviceNode); return -1; } bool luks::mount(Report& report, const QString& deviceNode, const QString& mountPoint) { if (!m_isCryptOpen) { qWarning() << "Cannot mount device" << deviceNode << "before decrypting it first."; return false; } if (m_isMounted) { qWarning() << "Cannot mount device" << deviceNode << "because it's already mounted."; return false; } Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; if (m_innerFs->canMount(mapperName(), mountPoint)) { if (m_innerFs->mount(report, mapperName(), mountPoint)) { m_isMounted = true; const QStorageInfo storageInfo = QStorageInfo(mountPoint); if (storageInfo.isValid() && !mountPoint.isEmpty()) setSectorsUsed( (storageInfo.bytesTotal() - storageInfo.bytesFree() + payloadOffset()) / sectorSize()); return true; } } else { ExternalCommand mountCmd( report, QStringLiteral("mount"), { QStringLiteral("--verbose"), mapperName(), mountPoint }); if (mountCmd.run() && mountCmd.exitCode() == 0) { m_isMounted = true; return true; } } return false; } bool luks::unmount(Report& report, const QString& deviceNode) { if (!m_isCryptOpen) { qWarning() << "Cannot unmount device" << deviceNode << "before decrypting it first."; return false; } if (!m_isMounted) { qWarning() << "Cannot unmount device" << deviceNode << "because it's not mounted."; return false; } Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; if (m_innerFs->canUnmount(mapperName())) { if (m_innerFs->unmount(report, mapperName())) { m_isMounted = false; return true; } } else { ExternalCommand unmountCmd( report, QStringLiteral("umount"), { QStringLiteral("--verbose"), QStringLiteral("--all-targets"), mapperName() }); if (unmountCmd.run() && unmountCmd.exitCode() == 0) { m_isMounted = false; return true; } } return false; } 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 { return QStringLiteral("luks-") + readOuterUUID(deviceNode); } QString luks::readLabel(const QString& deviceNode) const { if (m_isCryptOpen && m_innerFs) return m_innerFs->readLabel(mapperName()); return FileSystem::readLabel(deviceNode); } bool luks::writeLabel(Report& report, const QString&, const QString& newLabel) { Q_ASSERT(m_innerFs); return m_innerFs->writeLabel(report, mapperName(), newLabel); } bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) const { Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; if ( newLength - length() * sectorSize() > 0 ) { 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, mapperName(), m_PayloadSize); } else if (m_innerFs->resize(report, mapperName(), m_PayloadSize)) { ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // LUKS1 payload length is specified in multiples of 512 bytes QStringLiteral("resize"), mapperName() }); report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode); if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) return true; } report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition %1 failed.", deviceNode); return false; } bool luks::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const { Q_UNUSED(mountPoint) return resize(report, deviceNode, length); } QString luks::readUUID(const QString& deviceNode) const { QString outerUuid = readOuterUUID(deviceNode); if (m_isCryptOpen && m_innerFs) return m_innerFs->readUUID(mapperName()); return outerUuid; } QString luks::readOuterUUID(const QString &deviceNode) const { if ( deviceNode.isEmpty() ) return QString(); ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksUUID"), deviceNode }); if (cmd.run()) { if ( cmd.exitCode() ) { qWarning() << "Cannot get luksUUID for device" << deviceNode << "\tcryptsetup exit code" << cmd.exitCode() << "\toutput:" << cmd.output().trimmed(); return QString(); } QString outerUuid = cmd.output().trimmed(); const_cast< QString& >( m_outerUuid ) = outerUuid; return outerUuid; } return QStringLiteral("---"); } bool luks::updateUUID(Report& report, const QString& deviceNode) const { const QString uuid = QUuid::createUuid().toString().remove(QRegularExpression(QStringLiteral("\\{|\\}"))); ExternalCommand cmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("luksUUID"), deviceNode, QStringLiteral("--uuid"), uuid }); return cmd.run(-1) && cmd.exitCode() == 0; } void luks::getMapperName(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("lsblk"), { QStringLiteral("--list"), QStringLiteral("--noheadings"), QStringLiteral("--paths"), QStringLiteral("--json"), QStringLiteral("--output"), QStringLiteral("type,name"), deviceNode }); m_MapperName = QString(); 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("crypt")) { m_MapperName = deviceObject[QLatin1String("name")].toString(); break; } } } } void luks::getLuksInfo(const QString& deviceNode) { ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 0) { QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)")); QRegularExpressionMatch rem = re.match(cmd.output()); if (rem.hasMatch()) m_CipherName = rem.captured(1); else m_CipherName = QLatin1String("---"); re.setPattern(QStringLiteral("Cipher mode:\\s+(\\w+)")); rem = re.match(cmd.output()); if (rem.hasMatch()) m_CipherMode = rem.captured(1); else m_CipherMode = QLatin1String("---"); re.setPattern(QStringLiteral("Hash spec:\\s+(\\w+)")); rem = re.match(cmd.output()); if (rem.hasMatch()) m_HashName = rem.captured(1); else m_HashName = QLatin1String("---"); re.setPattern(QStringLiteral("MK bits:\\s+(\\d+)")); rem = re.match(cmd.output()); if (rem.hasMatch()) m_KeySize = rem.captured(1).toLongLong(); else m_KeySize = -1; re.setPattern(QStringLiteral("Payload offset:\\s+(\\d+)")); rem = re.match(cmd.output()); if (rem.hasMatch()) m_PayloadOffset = rem.captured(1).toLongLong() * 512; // assuming LUKS sector size is 512; else m_PayloadOffset = -1; } else { m_CipherName = QLatin1String("---"); m_CipherMode = QLatin1String("---"); m_HashName = QLatin1String("---"); m_KeySize = -1; m_PayloadOffset = -1; } } QString luks::outerUuid() const { return m_outerUuid; } 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; } } void luks::initLUKS() { setPayloadSize(); QString mapperNode = mapperName(); bool isCryptOpen = !mapperNode.isEmpty(); setCryptOpen(isCryptOpen); if (isCryptOpen) { loadInnerFileSystem(mapperNode); setMounted(detectMountStatus(innerFS(), mapperNode)); } } void luks::setPayloadSize() { ExternalCommand dmsetupCmd(QStringLiteral("dmsetup"), { QStringLiteral("table"), mapperName() }); dmsetupCmd.run(); QRegularExpression re(QStringLiteral("\\d+ (\\d+)")); QRegularExpressionMatch rem = re.match(dmsetupCmd.output()); if (rem.hasMatch()) m_PayloadSize = rem.captured(1).toLongLong() * sectorSize(); } 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) return true; 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 @@ -1,232 +1,232 @@ /************************************************************************* * Copyright (C) 2012 by Volker Lanz * * Copyright (C) 2013 by Andrius Štikonas * * Copyright (C) 2015-2016 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_LUKS_H) #define KPMCORE_LUKS_H #include "util/libpartitionmanagerexport.h" #include "fs/filesystem.h" #include class Report; class QString; class QWidget; namespace FS { /** A LUKS crypto file system. @author Andrius Štikonas */ 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 { unknown, dmcrypt, keyring }; public: void init() override; void scan(const QString& deviceNode) override; qint64 readUsedCapacity(const QString& deviceNode) const override; CommandSupportType supportGetUsed() const override { return m_GetUsed; } CommandSupportType supportGetLabel() const override { return m_GetLabel; } CommandSupportType supportCreate() const override { return m_Create; } CommandSupportType supportGrow() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Grow && m_innerFs) return m_innerFs->supportGrow(); return cmdSupportNone; } CommandSupportType supportGrowOnline() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Grow && m_innerFs) return m_innerFs->supportGrowOnline(); return cmdSupportNone; } CommandSupportType supportShrink() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Shrink && m_innerFs) return m_innerFs->supportShrink(); return cmdSupportNone; } CommandSupportType supportShrinkOnline() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Shrink && m_innerFs) return m_innerFs->supportShrinkOnline(); return cmdSupportNone; } CommandSupportType supportMove() const override { if (m_isCryptOpen) return cmdSupportNone; return m_Move; } CommandSupportType supportCheck() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Check && m_innerFs) return m_innerFs->supportCheck(); return cmdSupportNone; } CommandSupportType supportCheckOnline() const override { if (!m_isCryptOpen) return cmdSupportNone; if (m_Check && m_innerFs) return m_innerFs->supportCheckOnline(); return cmdSupportNone; } CommandSupportType supportCopy() const override { if (m_isCryptOpen) return cmdSupportNone; return m_Copy; } CommandSupportType supportBackup() const override { return m_Backup; } CommandSupportType supportSetLabel() const override { if (m_Check && m_innerFs) return m_innerFs->supportSetLabel(); return cmdSupportNone; } CommandSupportType supportUpdateUUID() const override { return m_UpdateUUID; } CommandSupportType supportGetUUID() const override { return m_GetUUID; } bool check(Report& report, const QString& deviceNode) const override; bool create(Report& report, const QString& deviceNode) override; SupportTool supportToolName() const override; bool supportToolFound() const override; QString readUUID(const QString& deviceNode) const override; bool updateUUID(Report& report, const QString& deviceNode) const override; bool resize(Report& report, const QString& deviceNode, qint64 length) const override; bool resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const override; QString readLabel(const QString& deviceNode) const override; bool writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) override; QString mountTitle() const override; QString unmountTitle() const override; QString cryptOpenTitle() const; QString cryptCloseTitle() const; void setPassphrase(const QString&); QString passphrase() const; bool canMount(const QString&, const QString&) const override; bool canUnmount(const QString&) const override; bool isMounted() const; void setMounted(bool mounted); bool canCryptOpen(const QString& deviceNode) const; bool canCryptClose(const QString& deviceNode) const; bool isCryptOpen() const; void setCryptOpen(bool cryptOpen); bool cryptOpen(QWidget* parent, const QString& deviceNode); bool cryptClose(const QString& deviceNode); void loadInnerFileSystem(const QString& mapperNode); void createInnerFileSystem(Type type); bool mount(Report& report, const QString& deviceNode, const QString& mountPoint) override; bool unmount(Report& report, const QString& deviceNode) override; FileSystem::Type type() const override; QString suggestedMapperName(const QString& deviceNode) const; void getMapperName(const QString& deviceNode); virtual void getLuksInfo(const QString& deviceNode); FileSystem* innerFS() const { return m_innerFs; } QString outerUuid() const; 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; } static bool canEncryptType(FileSystem::Type type); void initLUKS(); bool testPassphrase(const QString& deviceNode, const QString& passphrase) const; protected: virtual QString readOuterUUID(const QString& deviceNode) const; void setPayloadSize(); public: static CommandSupportType m_GetUsed; static CommandSupportType m_GetLabel; static CommandSupportType m_Create; static CommandSupportType m_Grow; static CommandSupportType m_Shrink; static CommandSupportType m_Move; static CommandSupportType m_Check; static CommandSupportType m_Copy; static CommandSupportType m_Backup; static CommandSupportType m_SetLabel; static CommandSupportType m_UpdateUUID; static CommandSupportType m_GetUUID; protected: mutable FileSystem* m_innerFs; mutable bool m_isCryptOpen; mutable bool m_cryptsetupFound; QString m_passphrase; bool m_isMounted; QString m_MapperName; QString m_CipherName; QString m_CipherMode; QString m_HashName; qint64 m_KeySize; qint64 m_PayloadOffset; qint64 m_PayloadSize; QString m_outerUuid; luks::KeyLocation m_KeyLocation = unknown; }; } #endif 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 @@ -1,145 +1,145 @@ /************************************************************************* * 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 "fs/luks2.h" #include "util/externalcommand.h" #include "util/report.h" #include #include 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) { } luks2::~luks2() { } 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) { Q_ASSERT(m_innerFs); Q_ASSERT(!m_passphrase.isEmpty()); ExternalCommand createCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("-s"), QStringLiteral("512"), QStringLiteral("--batch-mode"), QStringLiteral("--force-password"), QStringLiteral("--type"), QStringLiteral("luks2"), QStringLiteral("luksFormat"), deviceNode }); if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && createCmd.start(-1) && createCmd.waitFor() && createCmd.exitCode() == 0)) { return false; } ExternalCommand openCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("open"), deviceNode, suggestedMapperName(deviceNode) }); if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1) && openCmd.waitFor())) return false; setPayloadSize(); scan(deviceNode); if (mapperName().isEmpty()) return false; if (!m_innerFs->create(report, mapperName())) return false; return true; } bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) const { Q_ASSERT(m_innerFs); if (mapperName().isEmpty()) return false; if ( newLength - length() * sectorSize() > 0 ) { 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_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); } else if (m_innerFs->resize(report, mapperName(), m_PayloadSize)) { ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { 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_passphrase.isEmpty()) return false; cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); } cryptResizeCmd.start(-1); cryptResizeCmd.waitFor(); if ( cryptResizeCmd.exitCode() == 0 ) return true; } report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition %1 failed.", deviceNode); return false; } luks::KeyLocation luks2::keyLocation() { m_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; else if (rem.captured(1) == QStringLiteral("dm-crypt")) m_KeyLocation = dmcrypt; } } return m_KeyLocation; } } 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 @@ -1,306 +1,306 @@ /************************************************************************* * Copyright (C) 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 "fs/lvm2_pv.h" #include "core/device.h" #include "util/externalcommand.h" #include "util/capacity.h" #include #include namespace FS { FileSystem::CommandSupportType lvm2_pv::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_SetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType lvm2_pv::m_UpdateUUID = FileSystem::cmdSupportNone; 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) { } void lvm2_pv::init() { CommandSupportType lvmFound = findExternal(QStringLiteral("lvm")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = lvmFound; m_Check = lvmFound; m_Grow = lvmFound; m_Shrink = lvmFound; m_UpdateUUID = lvmFound; m_GetUsed = lvmFound; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; m_GetLabel = cmdSupportNone; m_Copy = cmdSupportNone; // Copying PV can confuse LVM } void lvm2_pv::scan(const QString& deviceNode) { getPESize(deviceNode); m_AllocatedPE = getAllocatedPE(deviceNode); m_TotalPE = getTotalPE(deviceNode); } bool lvm2_pv::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool lvm2_pv::supportToolName() const { return SupportTool(QStringLiteral("lvm2"), QUrl(QStringLiteral("http://sourceware.org/lvm2/"))); } qint64 lvm2_pv::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } qint64 lvm2_pv::readUsedCapacity(const QString& deviceNode) const { QString pvUsed = getpvField(QStringLiteral("pv_used"), deviceNode); QString metadataOffset = getpvField(QStringLiteral("pe_start"), deviceNode); return pvUsed.isEmpty() ? -1 : pvUsed.toLongLong() + metadataOffset.toLongLong(); } bool lvm2_pv::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("pvck"), QStringLiteral("--verbose"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool lvm2_pv::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("pvcreate"), QStringLiteral("--force"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool lvm2_pv::remove(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("pvremove"), QStringLiteral("--force"), QStringLiteral("--force"), QStringLiteral("--yes"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool lvm2_pv::resize(Report& report, const QString& deviceNode, qint64 length) const { bool rval = true; qint64 metadataOffset = getpvField(QStringLiteral("pe_start"), deviceNode).toLongLong(); qint64 lastPE = getTotalPE(deviceNode) - 1; // starts from 0 if (lastPE > 0) { // make sure that the PV is already in a VG qint64 targetPE = (length - metadataOffset) / peSize() - 1; // starts from 0 if (targetPE < lastPE) { //shrinking FS qint64 firstMovedPE = qMax(targetPE + 1, getAllocatedPE(deviceNode)); // starts from 1 ExternalCommand moveCmd(report, QStringLiteral("lvm"), { QStringLiteral("pvmove"), QStringLiteral("--alloc"), QStringLiteral("anywhere"), deviceNode + QStringLiteral(":") + QString::number(firstMovedPE) + QStringLiteral("-") + QString::number(lastPE), deviceNode + QStringLiteral(":") + QStringLiteral("0-") + QString::number(firstMovedPE - 1) }); rval = moveCmd.run(-1) && (moveCmd.exitCode() == 0 || moveCmd.exitCode() == 5); // FIXME: exit code 5: NO data to move } } ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("pvresize"), QStringLiteral("--yes"), QStringLiteral("--setphysicalvolumesize"), QString::number(length) + QStringLiteral("B"), deviceNode }); return rval && cmd.run(-1) && cmd.exitCode() == 0; } bool lvm2_pv::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const { Q_UNUSED(mountPoint) return resize(report, deviceNode, length); } bool lvm2_pv::updateUUID(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("lvm"), { QStringLiteral("pvchange"), QStringLiteral("--uuid"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } QString lvm2_pv::readUUID(const QString& deviceNode) const { return getpvField(QStringLiteral("pv_uuid"), deviceNode); } bool lvm2_pv::mount(Report& report, const QString& deviceNode, const QString& mountPoint) { Q_UNUSED(report) Q_UNUSED(deviceNode) Q_UNUSED(mountPoint) return false; } bool lvm2_pv::unmount(Report& report, const QString& deviceNode) { Q_UNUSED(deviceNode) Q_UNUSED(report) return false; } bool lvm2_pv::canMount(const QString& deviceNode, const QString& mountPoint) const { Q_UNUSED(deviceNode) Q_UNUSED(mountPoint) return false; } bool lvm2_pv::canUnmount(const QString& deviceNode) const { Q_UNUSED(deviceNode) return false; } qint64 lvm2_pv::getTotalPE(const QString& deviceNode) { QString pvPeCount = getpvField(QStringLiteral("pv_pe_count"), deviceNode); return pvPeCount.isEmpty() ? -1 : pvPeCount.toLongLong(); } qint64 lvm2_pv::getAllocatedPE(const QString& deviceNode) { QString pvPeAllocCount = getpvField(QStringLiteral("pv_pe_alloc_count"), deviceNode); return pvPeAllocCount.isEmpty() ? -1 : pvPeAllocCount.toLongLong(); } void lvm2_pv::getPESize(const QString& deviceNode) { QString vgExtentSize = getpvField(QStringLiteral("vg_extent_size"), deviceNode); m_PESize = vgExtentSize.isEmpty() ? -1 : vgExtentSize.toLongLong(); } /** Get pvs command output with field name * * @param fieldName LVM field name * @param deviceNode path to PV * @return raw output of pvs command, usually with many spaces */ QString lvm2_pv::getpvField(const QString& fieldName, const QString& deviceNode) { QStringList args = { QStringLiteral("pvs"), QStringLiteral("--foreign"), QStringLiteral("--readonly"), QStringLiteral("--noheadings"), QStringLiteral("--units"), QStringLiteral("B"), QStringLiteral("--nosuffix"), QStringLiteral("--options"), fieldName }; if (!deviceNode.isEmpty()) { args << deviceNode; } ExternalCommand cmd(QStringLiteral("lvm"), args, QProcess::ProcessChannelMode::SeparateChannels); if (cmd.run(-1) && cmd.exitCode() == 0) { return cmd.output().trimmed(); } return QString(); } QString lvm2_pv::getVGName(const QString& deviceNode) { return getpvField(QStringLiteral("vg_name"), deviceNode); } QList lvm2_pv::getPVinNode(const PartitionNode* parent) { QList partitions; if (parent == nullptr) return partitions; for (const auto &node : parent->children()) { const Partition* p = dynamic_cast(node); if (p == nullptr) continue; if (node->children().size() > 0) 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)); } return partitions; } /** construct a list of Partition objects for LVM PVs that are either unused or belong to some VG. * * @param devices list of Devices which we scan for LVM PVs * @return list of LVM PVs */ QList lvm2_pv::getPVs(const QList& devices) { QList partitions; for (auto const &d : devices) partitions.append(getPVinNode(d->partitionTable())); return partitions; } } QList LVM::pvList; LvmPV::LvmPV(const QString vgName, const Partition* p, bool isLuks) : m_vgName(vgName) , m_p(p) , m_isLuks(isLuks) { } 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 @@ -1,195 +1,195 @@ /************************************************************************* * Copyright (C) 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 "fs/nilfs2.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include #include #include namespace FS { FileSystem::CommandSupportType nilfs2::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType nilfs2::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void nilfs2::init() { m_Create = findExternal(QStringLiteral("mkfs.nilfs2")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = /*findExternal(QStringLiteral("fsck.nilfs2")) ? cmdSupportFileSystem : */cmdSupportNone; m_GetLabel = cmdSupportCore; m_SetLabel = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; m_UpdateUUID = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = findExternal(QStringLiteral("nilfs-resize")) ? cmdSupportFileSystem : cmdSupportNone; m_GetUsed = findExternal(QStringLiteral("nilfs-tune")) ? cmdSupportFileSystem : cmdSupportNone; m_Shrink = (m_Grow != cmdSupportNone && m_GetUsed != cmdSupportNone) ? cmdSupportFileSystem : cmdSupportNone; m_Copy =/* (m_Check != cmdSupportNone) ?*/ cmdSupportCore /*: cmdSupportNone*/; m_Move =/* (m_Check != cmdSupportNone) ?*/ cmdSupportCore /*: cmdSupportNone*/; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool nilfs2::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && // m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool nilfs2::supportToolName() const { return SupportTool(QStringLiteral("nilfs2-utils"), QUrl(QStringLiteral("http://code.google.com/p/nilfs2/"))); } qint64 nilfs2::minCapacity() const { return 128 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 nilfs2::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } int nilfs2::maxLabelLength() const { return 80; } bool nilfs2::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.nilfs2"), { deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool nilfs2::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.nilfs2"), { QStringLiteral("-f"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } qint64 nilfs2::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("nilfs-tune"), { QStringLiteral("-l"), deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 0) { QRegularExpression re(QStringLiteral("Block size:\\s+(\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); re.setPattern(QStringLiteral("Device size:\\s+(\\d+)")); QRegularExpressionMatch reDeviceSize = re.match(cmd.output()); re.setPattern(QStringLiteral("Free blocks count:\\s+(\\d+)")); QRegularExpressionMatch reFreeBlocks = re.match(cmd.output()); if (reBlockSize.hasMatch() && reDeviceSize.hasMatch() && reFreeBlocks.hasMatch()) return reDeviceSize.captured(1).toLongLong() - reBlockSize.captured(1).toLongLong() * reFreeBlocks.captured(1).toLongLong(); } return -1; } bool nilfs2::resize(Report& report, const QString& deviceNode, qint64 length) const { QTemporaryDir tempDir; if (!tempDir.isValid()) { report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition %1 failed: Could not create temp dir.", deviceNode); return false; } bool rval = false; ExternalCommand mountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--types"), QStringLiteral("nilfs2"), deviceNode, tempDir.path() }); if (mountCmd.run(-1) && mountCmd.exitCode() == 0) { ExternalCommand resizeCmd(report, QStringLiteral("nilfs-resize"), { QStringLiteral("--verbose"), QStringLiteral("--assume-yes"), deviceNode, QString::number(length) }); if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) rval = true; else report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition %1 failed: NILFS2 file system resize failed.", deviceNode); ExternalCommand unmountCmd(report, QStringLiteral("umount"), { tempDir.path() }); if (!unmountCmd.run(-1) && unmountCmd.exitCode() == 0) report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition %1: Unmount failed.", deviceNode); } else report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition %1 failed: Initial mount failed.", deviceNode); return rval; } bool nilfs2::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const { ExternalCommand resizeCmd(report, QStringLiteral("nilfs-resize"), { QStringLiteral("--verbose"), QStringLiteral("--assume-yes"), deviceNode, QString::number(length) }); if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) return true; report.line() << xi18nc("@info:progress", "Resizing NILFS2 file system on partition %1 failed: NILFS2 file system resize failed.", deviceNode); return false; } bool nilfs2::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("nilfs-tune"), { QStringLiteral("-l"), newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool nilfs2::updateUUID(Report& report, const QString& deviceNode) const { QUuid uuid = QUuid::createUuid(); ExternalCommand cmd(report, QStringLiteral("nilfs-tune"), { QStringLiteral("-U"), uuid.toString(), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,216 +1,216 @@ /************************************************************************* * Copyright (C) 2008,2009 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 "fs/ntfs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include "util/globallog.h" #include #include #include #include #include #include #include #include namespace FS { FileSystem::CommandSupportType ntfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ntfs::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void ntfs::init() { m_Shrink = m_Grow = m_Check = m_GetUsed = findExternal(QStringLiteral("ntfsresize")) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_SetLabel = findExternal(QStringLiteral("ntfslabel")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkfs.ntfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = findExternal(QStringLiteral("ntfsclone")) ? cmdSupportFileSystem : cmdSupportNone; m_Backup = cmdSupportCore; m_UpdateUUID = cmdSupportCore; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_GetUUID = cmdSupportCore; } bool ntfs::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool ntfs::supportToolName() const { return SupportTool(QStringLiteral("ntfs-3g"), QUrl(QStringLiteral("http://www.tuxera.com/community/ntfs-3g-download/"))); } qint64 ntfs::minCapacity() const { return 2 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 ntfs::maxCapacity() const { return 256 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB); } int ntfs::maxLabelLength() const { return 128; } qint64 ntfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("ntfsresize"), { QStringLiteral("--info"), QStringLiteral("--force"), QStringLiteral("--no-progress-bar"), deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 0) { qint64 usedBytes = -1; QRegularExpression re(QStringLiteral("resize at (\\d+) bytes")); QRegularExpressionMatch reUsedBytes = re.match(cmd.output()); if (reUsedBytes.hasMatch()) usedBytes = reUsedBytes.captured(1).toLongLong(); if (usedBytes > -1) return usedBytes; } return -1; } bool ntfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand writeCmd(report, QStringLiteral("ntfslabel"), { QStringLiteral("--force"), deviceNode, newLabel }, QProcess::SeparateChannels); if (!writeCmd.run(-1)) return false; return true; } bool ntfs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("ntfsresize"), { QStringLiteral("--no-progress-bar"), QStringLiteral("--info"), QStringLiteral("--force"), QStringLiteral("--verbose"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ntfs::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.ntfs"), { QStringLiteral("--quick"), QStringLiteral("--verbose"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ntfs::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const { ExternalCommand cmd(report, QStringLiteral("ntfsclone"), { QStringLiteral("--force"), QStringLiteral("--overwrite"), targetDeviceNode, sourceDeviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ntfs::resize(Report& report, const QString& deviceNode, qint64 length) const { QStringList args = { QStringLiteral("--no-progress-bar"), QStringLiteral("--force"), deviceNode, QStringLiteral("--size"), QString::number(length) }; QStringList dryRunArgs = args; dryRunArgs << QStringLiteral("--no-action"); ExternalCommand cmdDryRun(QStringLiteral("ntfsresize"), dryRunArgs); if (cmdDryRun.run(-1) && cmdDryRun.exitCode() == 0) { ExternalCommand cmd(report, QStringLiteral("ntfsresize"), args); return cmd.run(-1) && cmd.exitCode() == 0; } return false; } bool ntfs::updateUUID(Report& report, const QString& deviceNode) const { Q_UNUSED(report); ExternalCommand cmd(QStringLiteral("ntfslabel"), { QStringLiteral("--new-serial"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const { report.line() << xi18nc("@info:progress", "Updating boot sector for NTFS file system on partition %1.", deviceNode); qint64 n = firstSector(); char* s = reinterpret_cast(&n); #if Q_BYTE_ORDER == Q_BIG_ENDIAN std::swap(s[0], s[3]); std::swap(s[1], s[2]); #endif ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=28") }); cmd.write(QByteArray(s, sizeof(s))); if (!cmd.start()) { 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 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.waitFor(-1); Log() << xi18nc("@info:progress", "Updated NTFS boot sector for partition %1 successfully.", deviceNode); return true; } } 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 @@ -1,158 +1,158 @@ /************************************************************************* * 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 "fs/ocfs2.h" #include "util/externalcommand.h" #include "util/capacity.h" #include #include namespace FS { FileSystem::CommandSupportType ocfs2::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType ocfs2::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void ocfs2::init() { m_Create = findExternal(QStringLiteral("mkfs.ocfs2"), { QStringLiteral("--version") }) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("fsck.ocfs2"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = (m_Check != cmdSupportNone && findExternal(QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--version") }) && findExternal(QStringLiteral("debugfs.ocfs2"), { QStringLiteral("--version") })) ? cmdSupportFileSystem : cmdSupportNone; m_Shrink = cmdSupportNone; // TODO: it seems there's no way to get the FS usage with ocfs2 m_GetUsed = cmdSupportNone; m_SetLabel = findExternal(QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--version") }) ? cmdSupportFileSystem : cmdSupportNone; m_UpdateUUID = findExternal(QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--version") }) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool ocfs2::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool ocfs2::supportToolName() const { return SupportTool(QStringLiteral("ocfs2-tools"), QUrl(QStringLiteral("http://oss.oracle.com/projects/ocfs2-tools/"))); } qint64 ocfs2::minCapacity() const { return 14000 * Capacity::unitFactor(Capacity::Byte, Capacity::KiB); } qint64 ocfs2::maxCapacity() const { return 4 * Capacity::unitFactor(Capacity::Byte, Capacity::PiB); } qint64 ocfs2::readUsedCapacity(const QString& deviceNode) const { Q_UNUSED(deviceNode); return -1; } bool ocfs2::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.ocfs2"), { QStringLiteral("-f"), QStringLiteral("-y"), deviceNode }); return cmd.run(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 1 || cmd.exitCode() == 2); } 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 return false; } bool ocfs2::resize(Report& report, const QString& deviceNode, qint64 length) const { ExternalCommand cmdBlockSize(QStringLiteral("debugfs.ocfs2"), { QStringLiteral("--request"), QStringLiteral("stats"), deviceNode }); qint32 blockSize = -1; if (cmdBlockSize.run(-1) && cmdBlockSize.exitCode() == 0) { QRegularExpression re(QStringLiteral("Block Size Bits: (\\d+)")); QRegularExpressionMatch reBlockSizeBits = re.match(cmdBlockSize.output()); if (reBlockSizeBits.hasMatch()) blockSize = 1 << reBlockSizeBits.captured(1).toInt(); } if (blockSize == -1) return false; ExternalCommand cmd(report, QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--yes"), QStringLiteral("--volume-size"), deviceNode, QString::number(length / blockSize) }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ocfs2::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--label"), newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool ocfs2::updateUUID(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("tunefs.ocfs2"), { QStringLiteral("--uuid-reset"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,130 +1,130 @@ /************************************************************************* * 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 "fs/reiser4.h" #include "util/capacity.h" #include "util/externalcommand.h" #include #include namespace FS { FileSystem::CommandSupportType reiser4::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiser4::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiser4::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiser4::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiser4::m_Check = FileSystem::cmdSupportNone; 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) { } void reiser4::init() { m_GetLabel = cmdSupportCore; m_GetUsed = findExternal(QStringLiteral("debugfs.reiser4"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkfs.reiser4"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("fsck.reiser4"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_Move = m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Backup = cmdSupportCore; } bool reiser4::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && // m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone; // m_GetUUID != cmdSupportNone; } FileSystem::SupportTool reiser4::supportToolName() const { return SupportTool(QStringLiteral("reiser4progs"), QUrl(QStringLiteral("http://www.kernel.org/pub/linux/utils/fs/reiser4/reiser4progs/"))); } 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); } int reiser4::maxLabelLength() const { return 16; } qint64 reiser4::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("debugfs.reiser4"), { deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 16) { qint64 blocks = -1; QRegularExpression re(QStringLiteral("blocks:\\s+(\\d+)")); QRegularExpressionMatch reBlocks = re.match(cmd.output()); if (reBlocks.hasMatch()) blocks = reBlocks.captured(1).toLongLong(); qint64 blockSize = -1; re.setPattern(QStringLiteral("blksize:\\s+(\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); if (reBlockSize.hasMatch()) blockSize = reBlockSize.captured(1).toLongLong(); qint64 freeBlocks = -1; re.setPattern(QStringLiteral("free blocks:\\s+(\\d+)")); QRegularExpressionMatch reFreeBlocks = re.match(cmd.output()); if (reFreeBlocks.hasMatch()) freeBlocks = reFreeBlocks.captured(1).toLongLong(); if (blocks > - 1 && blockSize > -1 && freeBlocks > -1) return (blocks - freeBlocks) * blockSize; } return -1; } bool reiser4::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.reiser4"), { QStringLiteral("--yes"), QStringLiteral("--fix"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool reiser4::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.reiser4"), { QStringLiteral("--yes"), QStringLiteral("--force"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,179 +1,179 @@ /************************************************************************* * Copyright (C) 2008,2009 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 "fs/reiserfs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include #include #include #include namespace FS { FileSystem::CommandSupportType reiserfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_SetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType reiserfs::m_UpdateUUID = FileSystem::cmdSupportNone; 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) { } void reiserfs::init() { m_GetLabel = cmdSupportCore; m_GetUsed = findExternal(QStringLiteral("debugreiserfs"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_SetLabel = findExternal(QStringLiteral("reiserfstune")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkfs.reiserfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("fsck.reiserfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Move = m_Copy = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Grow = findExternal(QStringLiteral("resize_reiserfs"), {}, 16) ? cmdSupportFileSystem : cmdSupportNone; m_Shrink = (m_GetUsed != cmdSupportNone && m_Grow != cmdSupportNone) ? cmdSupportFileSystem : cmdSupportNone; m_Backup = cmdSupportCore; m_UpdateUUID = findExternal(QStringLiteral("reiserfstune")) ? cmdSupportFileSystem : cmdSupportNone; m_GetUUID = cmdSupportCore; } bool reiserfs::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool reiserfs::supportToolName() const { return SupportTool(QStringLiteral("reiserfsprogs"), QUrl(QStringLiteral("http://www.kernel.org/pub/linux/utils/fs/reiserfs/"))); } qint64 reiserfs::minCapacity() const { return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 reiserfs::maxCapacity() const { return 16 * Capacity::unitFactor(Capacity::Byte, Capacity::TiB) - Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } int reiserfs::maxLabelLength() const { return 16; } qint64 reiserfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("debugreiserfs"), { deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 16) { qint64 blockCount = -1; QRegularExpression re(QStringLiteral("Count of blocks[^:]+: (\\d+)")); QRegularExpressionMatch reBlockCount = re.match(cmd.output()); if (reBlockCount.hasMatch()) blockCount = reBlockCount.captured(1).toLongLong(); qint64 blockSize = -1; re.setPattern(QStringLiteral("Blocksize: (\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); if (reBlockSize.hasMatch()) blockSize = reBlockSize.captured(1).toLongLong(); qint64 freeBlocks = -1; re.setPattern(QStringLiteral("Free blocks[^:]+: (\\d+)")); QRegularExpressionMatch reFreeBlocks = re.match(cmd.output()); if (reFreeBlocks.hasMatch()) freeBlocks = reFreeBlocks.captured(1).toLongLong(); if (blockCount > -1 && blockSize > -1 && freeBlocks > -1) return (blockCount - freeBlocks) * blockSize; } return -1; } bool reiserfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("reiserfstune"), { QStringLiteral("--label"), newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool reiserfs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("fsck.reiserfs"), { QStringLiteral("--fix-fixable"), QStringLiteral("--quiet"), QStringLiteral("--yes"), deviceNode }); return cmd.run(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 1 || cmd.exitCode() == 256); } bool reiserfs::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.reiserfs"), { QStringLiteral("-f"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool reiserfs::resize(Report& report, const QString& deviceNode, qint64 length) const { ExternalCommand cmd(report, QStringLiteral("resize_reiserfs"), { deviceNode, QStringLiteral("-q"), QStringLiteral("-s"), QString::number(length) }); bool rval = cmd.write(QByteArrayLiteral("y\n")); if (!rval) return false; if (!cmd.start(-1)) return false; return cmd.waitFor(-1) && (cmd.exitCode() == 0 || cmd.exitCode() == 256); } bool reiserfs::resizeOnline(Report& report, const QString& deviceNode, const QString&, qint64 length) const { return resize(report, deviceNode, length); } bool reiserfs::updateUUID(Report& report, const QString& deviceNode) const { const QString uuid = QUuid::createUuid().toString().remove(QRegularExpression(QStringLiteral("\\{|\\}"))); ExternalCommand cmd(report, QStringLiteral("reiserfstune"), { QStringLiteral("--uuid"), uuid, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,184 +1,184 @@ /************************************************************************* * Copyright (C) 2017 by Pali Rohár * * * * 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/udf.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include #include namespace FS { constexpr qint64 MIN_UDF_BLOCKS = 300; constexpr qint64 MAX_UDF_BLOCKS = ((1ULL << 32) - 1); FileSystem::CommandSupportType udf::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType udf::m_SetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType udf::m_UpdateUUID = FileSystem::cmdSupportNone; 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) { } void udf::init() { m_GetUsed = findExternal(QStringLiteral("udfinfo"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone; m_SetLabel = m_UpdateUUID = findExternal(QStringLiteral("udflabel"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkudffs"), {}, 1) ? cmdSupportFileSystem : cmdSupportNone; 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")); } } bool udf::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_SetLabel != cmdSupportNone && m_UpdateUUID != cmdSupportNone && m_Create != cmdSupportNone; } FileSystem::SupportTool udf::supportToolName() const { return SupportTool(QStringLiteral("udftools"), QUrl(QStringLiteral("https://github.com/pali/udftools"))); } qint64 udf::minCapacity() const { return MIN_UDF_BLOCKS * sectorSize(); } qint64 udf::maxCapacity() const { return MAX_UDF_BLOCKS * sectorSize(); } int udf::maxLabelLength() const { return 126; } QValidator* udf::labelValidator(QObject *parent) const { QRegularExpressionValidator *m_LabelValidator = new QRegularExpressionValidator(parent); if (oldMkudffsVersion) { // Mkudffs from udftools prior to version 1.1 damages the label if it // contains non-ASCII characters. Therefore do not allow a label with // such characters with old versions of mkudffs. m_LabelValidator->setRegularExpression(QRegularExpression(QStringLiteral("[\\x{0001}-\\x{007F}]{0,126}"))); } else { // UDF label can only contain 126 bytes, either 126 ISO-8859-1 // (Latin 1) characters or 63 UCS-2BE characters. m_LabelValidator->setRegularExpression(QRegularExpression(QStringLiteral("[\\x{0001}-\\x{00FF}]{0,126}|[\\x{0001}-\\x{FFFF}]{0,63}"))); } return m_LabelValidator; } qint64 udf::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("udfinfo"), { QStringLiteral("--utf8"), deviceNode }); if (!cmd.run(-1) || cmd.exitCode() != 0) return -1; QRegularExpressionMatch reBlockSize = QRegularExpression(QStringLiteral("^blocksize=([0-9]+)$"), QRegularExpression::MultilineOption).match(cmd.output()); QRegularExpressionMatch reUsedBlocks = QRegularExpression(QStringLiteral("^usedblocks=([0-9]+)$"), QRegularExpression::MultilineOption).match(cmd.output()); if (!reBlockSize.hasMatch() || !reUsedBlocks.hasMatch()) return -1; qint64 blockSize = reBlockSize.captured(1).toLongLong(); qint64 usedBlocks = reUsedBlocks.captured(1).toLongLong(); return usedBlocks * blockSize; } bool udf::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("udflabel"), { QStringLiteral("--utf8"), deviceNode, newLabel }); return cmd.run(-1) && cmd.exitCode() == 0; } bool udf::updateUUID(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("udflabel"), { QStringLiteral("--utf8"), QStringLiteral("--uuid=random"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool udf::create(Report& report, const QString& deviceNode) { return createWithLabel(report, deviceNode, QString()); } bool udf::createWithLabel(Report& report, const QString& deviceNode, const QString& label) { // It is not possible to create UDF filesystem without a label or with empty label // When --lvid or --vid option is not specified, mkudffs use sane default QStringList labelArgs; if (!label.isEmpty()) { // The Volume Identifier (--vid) can only contain 30 bytes, either 30 // ISO-8859-1 (Latin 1) characters or 15 UCS-2BE characters. Store the // most characters possible in the Volume Identifier. Either up to 15 // UCS-2BE characters when a character needing 16-bit encoding is found in // the first 15 characters, or up to 30 characters when a character // needing 16-bit encoding is found in the second 15 characters. const QRegularExpression nonLatin1RegExp = QRegularExpression(QStringLiteral("[^\\x{0000}-\\x{00FF}]")); QString shortLabel = label.left(30); int firstNonLatin1Pos = shortLabel.indexOf(nonLatin1RegExp); if (firstNonLatin1Pos != -1 && firstNonLatin1Pos < 15) shortLabel = shortLabel.left(15); else if (firstNonLatin1Pos != -1 && firstNonLatin1Pos < 30) shortLabel = shortLabel.left(firstNonLatin1Pos); // UDF Logical Volume Identifier (--lvid) represents the label, but blkid // (from util-linux) prior to version v2.26 reads the Volume Identifier // (--vid). Therefore for compatibility reasons store the label in both // locations. labelArgs << QStringLiteral("--lvid=") + label; labelArgs << QStringLiteral("--vid=") + shortLabel; } QStringList cmdArgs; cmdArgs << QStringLiteral("--utf8"); // TODO: Add GUI option for choosing different optical disks and UDF revision // For now format as UDF revision 2.01 for hard disk media type cmdArgs << QStringLiteral("--media-type=hd"); cmdArgs << QStringLiteral("--udfrev=0x201"); // mkudffs from udftools prior to 1.1 is not able to detect logical (sector) size // and UDF block size must match logical sector size of underlying media cmdArgs << QStringLiteral("--blocksize=") + QString::number(sectorSize()); cmdArgs << labelArgs; cmdArgs << deviceNode; ExternalCommand cmd(report, QStringLiteral("mkudffs"), cmdArgs); return cmd.run(-1) && cmd.exitCode() == 0; } } 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 @@ -1,30 +1,30 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/ufs.h" namespace FS { FileSystem::CommandSupportType ufs::m_Move = FileSystem::cmdSupportCore; 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 @@ -1,33 +1,33 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/unformatted.h" 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) { } bool unformatted::create(Report&, const QString&) { return true; } } 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 @@ -1,33 +1,33 @@ /************************************************************************* * Copyright (C) 2008 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 .* *************************************************************************/ #include "fs/unknown.h" 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) { } bool unknown::canMount(const QString & deviceNode, const QString & mountPoint) const { Q_UNUSED(deviceNode) Q_UNUSED(mountPoint) return false; } } 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 @@ -1,203 +1,203 @@ /************************************************************************* * 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 "fs/xfs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include #include namespace FS { FileSystem::CommandSupportType xfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType xfs::m_Copy = FileSystem::cmdSupportNone; 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) { } void xfs::init() { m_GetLabel = cmdSupportCore; m_SetLabel = m_GetUsed = findExternal(QStringLiteral("xfs_db")) ? cmdSupportFileSystem : cmdSupportNone; m_Create = findExternal(QStringLiteral("mkfs.xfs")) ? cmdSupportFileSystem : cmdSupportNone; m_Check = findExternal(QStringLiteral("xfs_repair")) ? cmdSupportFileSystem : cmdSupportNone; m_Grow = (findExternal(QStringLiteral("xfs_growfs"), { QStringLiteral("-V") }) && m_Check != cmdSupportNone) ? cmdSupportFileSystem : cmdSupportNone; m_Copy = findExternal(QStringLiteral("xfs_copy")) ? cmdSupportFileSystem : cmdSupportNone; m_Move = (m_Check != cmdSupportNone) ? cmdSupportCore : cmdSupportNone; m_Backup = cmdSupportCore; } bool xfs::supportToolFound() const { return m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && m_Create != cmdSupportNone && m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && m_Copy != cmdSupportNone && m_Move != cmdSupportNone && m_Backup != cmdSupportNone; // m_GetUUID != cmdSupportNone; } FileSystem::SupportTool xfs::supportToolName() const { return SupportTool(QStringLiteral("xfsprogs"), QUrl(QStringLiteral("http://oss.sgi.com/projects/xfs/"))); } qint64 xfs::minCapacity() const { return 32 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 xfs::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } int xfs::maxLabelLength() const { return 12; } qint64 xfs::readUsedCapacity(const QString& deviceNode) const { ExternalCommand cmd(QStringLiteral("xfs_db"), { QStringLiteral("-c"), QStringLiteral("sb 0"), QStringLiteral("-c"), QStringLiteral("print"), deviceNode }); if (cmd.run(-1) && cmd.exitCode() == 0) { qint64 dBlocks = -1; QRegularExpression re(QStringLiteral("dblocks = (\\d+)")); QRegularExpressionMatch reDBlocks = re.match(cmd.output()); if (reDBlocks.hasMatch()) dBlocks = reDBlocks.captured(1).toLongLong(); qint64 blockSize = -1; re.setPattern(QStringLiteral("blocksize = (\\d+)")); QRegularExpressionMatch reBlockSize = re.match(cmd.output()); if (reBlockSize.hasMatch()) blockSize = reBlockSize.captured(1).toLongLong(); qint64 fdBlocks = -1; re.setPattern(QStringLiteral("fdblocks = (\\d+)")); QRegularExpressionMatch reFdBlocks = re.match(cmd.output()); if (reFdBlocks.hasMatch()) fdBlocks = reFdBlocks.captured(1).toLongLong(); if (dBlocks > -1 && blockSize > -1 && fdBlocks > -1) return (dBlocks - fdBlocks) * blockSize; } return -1; } bool xfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { ExternalCommand cmd(report, QStringLiteral("xfs_db"), { QStringLiteral("-x"), QStringLiteral("-c"), QStringLiteral("sb 0"), QStringLiteral("-c"), QStringLiteral("label ") + newLabel, deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool xfs::check(Report& report, const QString& deviceNode) const { ExternalCommand cmd(report, QStringLiteral("xfs_repair"), { QStringLiteral("-v"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool xfs::create(Report& report, const QString& deviceNode) { ExternalCommand cmd(report, QStringLiteral("mkfs.xfs"), { QStringLiteral("-f"), deviceNode }); return cmd.run(-1) && cmd.exitCode() == 0; } bool xfs::copy(Report& report, const QString& targetDeviceNode, const QString& sourceDeviceNode) const { ExternalCommand cmd(report, QStringLiteral("xfs_copy"), { sourceDeviceNode, targetDeviceNode }); // xfs_copy behaves a little strangely. It apparently kills itself at the end of main, causing QProcess // to report that it crashed. // See http://oss.sgi.com/archives/xfs/2004-11/msg00169.html // So we cannot rely on QProcess::exitStatus() and thus not on ExternalCommand::run() returning true. cmd.run(-1); return cmd.exitCode() == 0; } bool xfs::resize(Report& report, const QString& deviceNode, qint64) const { QTemporaryDir tempDir; if (!tempDir.isValid()) { report.line() << xi18nc("@info:progress", "Resizing XFS file system on partition %1 failed: Could not create temp dir.", deviceNode); return false; } bool rval = false; ExternalCommand mountCmd(report, QStringLiteral("mount"), { QStringLiteral("--verbose"), QStringLiteral("--types"), QStringLiteral("xfs"), deviceNode, tempDir.path() }); if (mountCmd.run(-1)) { ExternalCommand resizeCmd(report, QStringLiteral("xfs_growfs"), { tempDir.path() }); if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) rval = true; else report.line() << xi18nc("@info:progress", "Resizing XFS file system on partition %1 failed: xfs_growfs failed.", deviceNode); ExternalCommand unmountCmd(report, QStringLiteral("umount"), { tempDir.path() }); if (!unmountCmd.run(-1)) report.line() << xi18nc("@info:progress", "Resizing XFS file system on partition %1 failed: Unmount failed.", deviceNode); } else report.line() << xi18nc("@info:progress", "Resizing XFS file system on partition %1 failed: Initial mount failed.", deviceNode); return rval; } bool xfs::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64) const { ExternalCommand resizeCmd(report, QStringLiteral("xfs_growfs"), { mountPoint }); if (resizeCmd.run(-1) && resizeCmd.exitCode() == 0) return true; report.line() << xi18nc("@info:progress", "Resizing XFS file system on partition %1 failed: xfs_growfs failed.", deviceNode); return false; } } 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 @@ -1,102 +1,102 @@ /************************************************************************* * 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 "fs/zfs.h" #include "util/externalcommand.h" #include "util/capacity.h" #include "util/report.h" #include namespace FS { FileSystem::CommandSupportType zfs::m_GetUsed = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_GetLabel = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Create = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Grow = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Shrink = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Move = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Check = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Copy = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_Backup = FileSystem::cmdSupportNone; FileSystem::CommandSupportType zfs::m_SetLabel = FileSystem::cmdSupportNone; 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) { } void zfs::init() { m_SetLabel = findExternal(QStringLiteral("zpool"), {}, 2) ? cmdSupportFileSystem : cmdSupportNone; m_GetLabel = cmdSupportCore; m_Backup = cmdSupportCore; m_GetUUID = cmdSupportCore; } bool zfs::supportToolFound() const { return // m_GetUsed != cmdSupportNone && m_GetLabel != cmdSupportNone && m_SetLabel != cmdSupportNone && // m_Create != cmdSupportNone && // m_Check != cmdSupportNone && // m_UpdateUUID != cmdSupportNone && // m_Grow != cmdSupportNone && // m_Shrink != cmdSupportNone && // m_Copy != cmdSupportNone && // m_Move != cmdSupportNone && m_Backup != cmdSupportNone && m_GetUUID != cmdSupportNone; } FileSystem::SupportTool zfs::supportToolName() const { return SupportTool(QStringLiteral("zfs"), QUrl(QStringLiteral("http://zfsonlinux.org/"))); } qint64 zfs::minCapacity() const { return 64 * Capacity::unitFactor(Capacity::Byte, Capacity::MiB); } qint64 zfs::maxCapacity() const { return Capacity::unitFactor(Capacity::Byte, Capacity::EiB); } bool zfs::remove(Report& report, const QString& deviceNode) const { Q_UNUSED(deviceNode) ExternalCommand cmd(report, QStringLiteral("zpool"), { QStringLiteral("destroy"), QStringLiteral("-f"), label() }); return cmd.run(-1) && cmd.exitCode() == 0; } bool zfs::writeLabel(Report& report, const QString& deviceNode, const QString& newLabel) { Q_UNUSED(deviceNode) ExternalCommand cmd1(report, QStringLiteral("zpool"), { QStringLiteral("export"), label() }); ExternalCommand cmd2(report, QStringLiteral("zpool"), { QStringLiteral("import"), label(), newLabel }); return cmd1.run(-1) && cmd1.exitCode() == 0 && cmd2.run(-1) && cmd2.exitCode() == 0; } } 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 @@ -1,152 +1,152 @@ /************************************************************************* * Copyright (C) 2008, 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 .* *************************************************************************/ #include "gui/partwidget.h" #include "core/partition.h" #include "fs/filesystem.h" #include "util/capacity.h" #include #include #include #include /** Creates a new PartWidget @param parent pointer to the parent widget @param p pointer to the Partition this widget will show. must not be nullptr. */ PartWidget::PartWidget(QWidget* parent, Partition* p) : PartWidgetBase(parent), m_Partition(nullptr), m_Active(false) { setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); init(p); m_fileSystemColorCode = FileSystem::defaultColorCode; } void PartWidget::init(Partition* p) { m_Partition = p; if (partition()) setToolTip(partition()->deviceNode() + QStringLiteral("\n") + partition()->fileSystem().name() + QStringLiteral(" ") + QString(Capacity::formatByteSize(partition()->capacity()))); else setToolTip(QString()); updateChildren(); } /** Updates the widget's children */ void PartWidget::updateChildren() { if (partition()) { for (const auto &w : childWidgets()) { w->setVisible(false); w->deleteLater(); w->setParent(nullptr); } for (const auto &child : partition()->children()) { QWidget* w = new PartWidget(this, child); w->setVisible(true); } positionChildren(this, partition()->children(), childWidgets()); } } void PartWidget::setFileSystemColorCode(const std::vector& colorCode) { m_fileSystemColorCode = colorCode; repaint(); } void PartWidget::resizeEvent(QResizeEvent*) { if (partition()) positionChildren(this, partition()->children(), childWidgets()); } QColor PartWidget::activeColor(const QColor& col) const { return isActive() ? col.darker(190) : col; } void PartWidget::paintEvent(QPaintEvent*) { if (partition() == nullptr) return; const int usedPercentage = static_cast(partition()->used() * 100 / partition()->capacity()); const int w = width() * usedPercentage / 100; QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing); 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); const QColor light = base.lighter(120); // draw free space background drawGradient(&painter, light, QRect(0, 0, width(), height()), isActive()); // draw used space in front of that drawGradient(&painter, dark, QRect(0, 0, w, height() - 1)); } else drawGradient(&painter, base, QRect(0, 0, width(), height()), isActive()); // draw name and size QString text = partition()->deviceNode().remove(QStringLiteral("/dev/")) + QStringLiteral("\n") + QString(Capacity::formatByteSize(partition()->capacity())); const QRect textRect(0, 0, width() - 1, height() - 1); const QRect boundingRect = painter.boundingRect(textRect, Qt::AlignVCenter | Qt::AlignHCenter, text); if (boundingRect.x() > PartWidgetBase::borderWidth() && boundingRect.y() > PartWidgetBase::borderHeight()) { if (isActive()) painter.setPen(QColor(255, 255, 255)); painter.drawText(textRect, Qt::AlignVCenter | Qt::AlignHCenter, text); } } void PartWidget::drawGradient(QPainter* painter, const QColor& color, const QRect& rect, bool active) const { if (rect.width() < 8) return; QStyleOptionButton option; option.initFrom(this); option.rect = rect; option.palette.setColor(QPalette::Button, color); option.palette.setColor(QPalette::Window, color); option.state |= QStyle::State_Raised; if (!active) option.state &= ~QStyle::State_MouseOver; else option.state |= QStyle::State_MouseOver; style()->drawControl(QStyle::CE_PushButtonBevel, &option, painter, this); } 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 @@ -1,92 +1,92 @@ /************************************************************************* * Copyright (C) 2008, 2011 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 "jobs/createfilesystemjob.h" #include "backend/corebackend.h" #include "backend/corebackendmanager.h" #include "backend/corebackenddevice.h" #include "backend/corebackendpartitiontable.h" #include "core/device.h" #include "core/partition.h" #include "fs/filesystem.h" #include "util/report.h" #include /** Creates a new CreateFileSystemJob @param p the Partition the FileSystem to create is on */ CreateFileSystemJob::CreateFileSystemJob(Device& d, Partition& p, const QString& label) : Job(), m_Device(d), m_Partition(p), m_Label(label) { } bool CreateFileSystemJob::run(Report& parent) { bool rval = false; Report* report = jobStarted(parent); - if (partition().fileSystem().type() == FileSystem::Unformatted) + if (partition().fileSystem().type() == FileSystem::Type::Unformatted) return true; bool createResult; if (partition().fileSystem().supportCreate() == FileSystem::cmdSupportFileSystem) { if (partition().fileSystem().supportCreateWithLabel() == FileSystem::cmdSupportFileSystem) createResult = partition().fileSystem().createWithLabel(*report, partition().deviceNode(), m_Label); else createResult = partition().fileSystem().create(*report, partition().deviceNode()); if (createResult) { if (device().type() == Device::Disk_Device) { std::unique_ptr backendDevice = CoreBackendManager::self()->backend()->openDevice(device()); if (backendDevice) { std::unique_ptr backendPartitionTable = backendDevice->openPartitionTable(); if (backendPartitionTable) { if (backendPartitionTable->setPartitionSystemType(*report, partition())) { rval = true; backendPartitionTable->commit(); } else report->line() << xi18nc("@info:progress", "Failed to set the system type for the file system on partition %1.", partition().deviceNode()); } 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 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) { rval = true; } } } jobFinished(*report, rval); return rval; } QString CreateFileSystemJob::description() const { return xi18nc("@info:progress", "Create file system %1 on partition %2", partition().fileSystem().name(), partition().deviceNode()); } 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 @@ -1,112 +1,112 @@ /************************************************************************* * 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 "jobs/restorefilesystemjob.h" #include "backend/corebackend.h" #include "backend/corebackendmanager.h" #include "backend/corebackenddevice.h" #include "backend/corebackendpartitiontable.h" #include "core/partition.h" #include "core/device.h" #include "core/copysourcefile.h" #include "core/copytargetdevice.h" #include "fs/filesystem.h" #include "fs/filesystemfactory.h" #include "util/report.h" #include /** Creates a new RestoreFileSystemJob @param targetdevice the Device the FileSystem is to be restored to @param targetpartition the Partition the FileSystem is to be restore to @param filename the file name with the image file to restore */ RestoreFileSystemJob::RestoreFileSystemJob(Device& targetdevice, Partition& targetpartition, const QString& filename) : Job(), m_TargetDevice(targetdevice), m_TargetPartition(targetpartition), m_FileName(filename) { } qint32 RestoreFileSystemJob::numSteps() const { return 100; } bool RestoreFileSystemJob::run(Report& parent) { // Restoring is file system independent because we currently have no way of // detecting the file system in a given image file. We cannot even find out if the // file the user gave us is a valid image file or just some junk. bool rval = false; Report* report = jobStarted(parent); // Again, a scope for copyTarget and copySource. See MoveFileSystemJob::run() { // FileSystems are restored to _partitions_, so don't use first and last sector of file system here CopyTargetDevice copyTarget(targetDevice(), targetPartition().firstByte(), targetPartition().lastByte()); CopySourceFile copySource(fileName()); if (!copySource.open()) report->line() << xi18nc("@info:progress", "Could not open backup file %1 to restore from.", fileName()); else if (!copyTarget.open()) report->line() << xi18nc("@info:progress", "Could not open target partition %1 to restore to.", targetPartition().deviceNode()); else { rval = copyBlocks(*report, copyTarget, copySource); if (rval) { // create a new file system for what was restored with the length of the image file const qint64 newLastSector = targetPartition().firstSector() + copySource.length() - 1; 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(); if (backendPartitionTable) t = backendPartitionTable->detectFileSystemBySector(*report, targetDevice(), targetPartition().firstSector()); } FileSystem* fs = FileSystemFactory::create(t, targetPartition().firstSector(), newLastSector, targetPartition().sectorSize()); targetPartition().deleteFileSystem(); targetPartition().setFileSystem(fs); } report->line() << xi18nc("@info:progress", "Closing device. This may take a few seconds."); } } jobFinished(*report, rval); return rval; } QString RestoreFileSystemJob::description() const { return xi18nc("@info:progress", "Restore the file system from file %1 to partition %2", fileName(), targetPartition().deviceNode()); } 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 @@ -1,135 +1,135 @@ /************************************************************************* * 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 "ops/newoperation.h" #include "core/partition.h" #include "core/device.h" #include "core/partitionnode.h" #include "jobs/createpartitionjob.h" #include "jobs/createfilesystemjob.h" #include "jobs/setfilesystemlabeljob.h" #include "jobs/setpartflagsjob.h" #include "jobs/checkfilesystemjob.h" #include "fs/filesystem.h" #include "fs/filesystemfactory.h" #include "util/capacity.h" #include #include /** Creates a new NewOperation. @param d the Device to create a new Partition on @param p pointer to the new Partition to create. May not be nullptr. */ NewOperation::NewOperation(Device& d, Partition* p) : Operation(), m_TargetDevice(d), m_NewPartition(p), m_CreatePartitionJob(new CreatePartitionJob(targetDevice(), newPartition())), m_CreateFileSystemJob(nullptr), m_SetPartFlagsJob(nullptr), m_SetFileSystemLabelJob(nullptr), m_CheckFileSystemJob(nullptr) { addJob(createPartitionJob()); 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 // label. The operation stack will merge these operations with this one here // and if the jobs don't exist things will break. 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()); } m_SetFileSystemLabelJob = new SetFileSystemLabelJob(newPartition(), fs.label()); addJob(setLabelJob()); m_CheckFileSystemJob = new CheckFileSystemJob(newPartition()); addJob(checkJob()); } } NewOperation::~NewOperation() { if (status() == StatusPending) delete m_NewPartition; } bool NewOperation::targets(const Device& d) const { return d == targetDevice(); } bool NewOperation::targets(const Partition& p) const { return p == newPartition(); } void NewOperation::preview() { insertPreviewPartition(targetDevice(), newPartition()); } void NewOperation::undo() { removePreviewPartition(targetDevice(), newPartition()); } QString NewOperation::description() const { return xi18nc("@info:status", "Create a new partition (%1, %2) on %3", Capacity::formatByteSize(newPartition().capacity()), newPartition().fileSystem().name(), targetDevice().deviceNode()); } /** Can a Partition be created somewhere? @param p the Partition where a new Partition is to be created, may be nullptr @return true if a new Partition can be created in @p p */ bool NewOperation::canCreateNew(const Partition* p) { return p != nullptr && p->roles().has(PartitionRole::Unallocated); } Partition* NewOperation::createNew(const Partition& cloneFrom, FileSystem::Type type) { Partition* p = new Partition(cloneFrom); p->deleteFileSystem(); p->setFileSystem(FileSystemFactory::create(type, p->firstSector(), p->lastSector(), p->sectorSize())); p->setState(Partition::StateNew); p->setPartitionPath(QString()); return p; } 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 @@ -1,75 +1,75 @@ /************************************************************************* * 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 "ops/removevolumegroupoperation.h" #include "jobs/removevolumegroupjob.h" #include "core/partition.h" #include "core/partitiontable.h" #include "core/volumemanagerdevice.h" #include #include /** Creates a new RemoveVolumeGroupOperation. */ RemoveVolumeGroupOperation::RemoveVolumeGroupOperation(VolumeManagerDevice& d) : Operation(), m_RemoveVolumeGroupJob(new RemoveVolumeGroupJob(d)), m_Device(d), m_PartitionTable(nullptr) { addJob(removeVolumeGroupJob()); } QString RemoveVolumeGroupOperation::description() const { return xi18nc("@info/plain", "Remove a LVM volume group."); } void RemoveVolumeGroupOperation::preview() { m_PartitionTable = device().partitionTable(); device().setPartitionTable(new PartitionTable(PartitionTable::vmd, 0, device().totalLogical() - 1)); } void RemoveVolumeGroupOperation::undo() { device().setPartitionTable(m_PartitionTable); } /** Check if Volume Group can be safely removed * * @param dev VolumeManagerDevice with initialized partitions * @return true if there are no LVM partitions. */ bool RemoveVolumeGroupOperation::isRemovable(const VolumeManagerDevice* dev) { // TODO: allow removal when LVs are inactive. if (dev->type() == Device::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) return false; else - if (dev->partitionTable()->children().first()->fileSystem().type() == FileSystem::Unknown) + if (dev->partitionTable()->children().first()->fileSystem().type() == FileSystem::Type::Unknown) return true; } return false; } 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 @@ -1,233 +1,233 @@ /************************************************************************* * 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 "ops/restoreoperation.h" #include "core/partition.h" #include "core/device.h" #include "core/partitiontable.h" #include "core/partitionnode.h" #include "jobs/createpartitionjob.h" #include "jobs/deletepartitionjob.h" #include "jobs/checkfilesystemjob.h" #include "jobs/restorefilesystemjob.h" #include "jobs/resizefilesystemjob.h" #include "fs/filesystem.h" #include "fs/filesystemfactory.h" #include "fs/luks.h" #include "util/capacity.h" #include "util/report.h" #include #include #include #include /** Creates a new RestoreOperation. @param d the Device to restore the Partition to @param p pointer to the Partition that will be restored. May not be nullptr. @param filename name of the image file to restore from */ RestoreOperation::RestoreOperation(Device& d, Partition* p, const QString& filename) : Operation(), m_TargetDevice(d), m_RestorePartition(p), m_FileName(filename), m_OverwrittenPartition(nullptr), m_MustDeleteOverwritten(false), m_ImageLength(QFileInfo(filename).size() / 512), // 512 being the "sector size" of an image file. m_CreatePartitionJob(nullptr), m_RestoreJob(nullptr), m_CheckTargetJob(nullptr), m_MaximizeJob(nullptr) { restorePartition().setState(Partition::StateRestore); Q_ASSERT(targetDevice().partitionTable()); Partition* dest = targetDevice().partitionTable()->findPartitionBySector(restorePartition().firstSector(), PartitionRole(PartitionRole::Primary | PartitionRole::Logical | PartitionRole::Unallocated)); if (dest == nullptr) qWarning() << "destination partition not found at sector " << restorePartition().firstSector(); Q_ASSERT(dest); if (dest && !dest->roles().has(PartitionRole::Unallocated)) { restorePartition().setLastSector(dest->lastSector()); setOverwrittenPartition(dest); removePreviewPartition(targetDevice(), *dest); } if (!overwrittenPartition()) addJob(m_CreatePartitionJob = new CreatePartitionJob(targetDevice(), restorePartition())); addJob(m_RestoreJob = new RestoreFileSystemJob(targetDevice(), restorePartition(), fileName())); addJob(m_CheckTargetJob = new CheckFileSystemJob(restorePartition())); addJob(m_MaximizeJob = new ResizeFileSystemJob(targetDevice(), restorePartition())); } RestoreOperation::~RestoreOperation() { if (status() == StatusPending) delete m_RestorePartition; if (status() == StatusFinishedSuccess || status() == StatusFinishedWarning || status() == StatusError) cleanupOverwrittenPartition(); } bool RestoreOperation::targets(const Device& d) const { return d == targetDevice(); } bool RestoreOperation::targets(const Partition& p) const { return p == restorePartition(); } void RestoreOperation::preview() { insertPreviewPartition(targetDevice(), restorePartition()); } void RestoreOperation::undo() { removePreviewPartition(targetDevice(), restorePartition()); if (overwrittenPartition()) insertPreviewPartition(targetDevice(), *overwrittenPartition()); } bool RestoreOperation::execute(Report& parent) { bool rval = false; bool warning = false; Report* report = parent.newChild(description()); if (overwrittenPartition()) restorePartition().setPartitionPath(overwrittenPartition()->devicePath()); if (overwrittenPartition() || (rval = createPartitionJob()->run(*report))) { restorePartition().setState(Partition::StateNone); if ((rval = restoreJob()->run(*report))) { if ((rval = checkTargetJob()->run(*report))) { // If the partition was written over an existing one, the partition itself may now // be larger than the filesystem, so maximize the filesystem to the partition's size // or the image length, whichever is larger. If this fails, don't return an error, just // warn the user. if ((warning = !maximizeJob()->run(*report))) report->line() << xi18nc("@info:status", "Maximizing file system on target partition %1 to the size of the partition failed.", restorePartition().deviceNode()); } else report->line() << xi18nc("@info:status", "Checking target file system on partition %1 after the restore failed.", restorePartition().deviceNode()); } else { if (!overwrittenPartition()) DeletePartitionJob(targetDevice(), restorePartition()).run(*report); report->line() << xi18nc("@info:status", "Restoring file system failed."); } } else report->line() << xi18nc("@info:status", "Creating the destination partition to restore to failed."); if (rval) setStatus(warning ? StatusFinishedWarning : StatusFinishedSuccess); else setStatus(StatusError); report->setStatus(xi18nc("@info:status (success, error, warning...) of operation", "%1: %2", description(), statusText())); return rval; } QString RestoreOperation::description() const { if (overwrittenPartition()) return xi18nc("@info:status", "Restore partition from %1 to %2", fileName(), overwrittenPartition()->deviceNode()); return xi18nc("@info:status", "Restore partition on %1 at %2 from %3", targetDevice().deviceNode(), Capacity::formatByteSize(restorePartition().firstSector() * targetDevice().logicalSize()), fileName()); } void RestoreOperation::setOverwrittenPartition(Partition* p) { // This is copied from CopyOperation. One day we might create a common base class ;-) cleanupOverwrittenPartition(); m_OverwrittenPartition = p; m_MustDeleteOverwritten = (p && p->state() == Partition::StateNone); } void RestoreOperation::cleanupOverwrittenPartition() { if (mustDeleteOverwritten()) { delete overwrittenPartition(); m_OverwrittenPartition = nullptr; } } /** Can a Partition be restored to somewhere? @param p the Partition in question, may be nullptr. @return true if a Partition can be restored to @p p. */ bool RestoreOperation::canRestore(const Partition* p) { if (p == nullptr) return false; if (p->isMounted()) return false; if (p->roles().has(PartitionRole::Extended)) return false; if (p->roles().has(PartitionRole::Luks)) { const FS::luks* luksFs = static_cast(&p->fileSystem()); return luksFs->mapperName().isEmpty(); } return true; } /** Creates a new Partition to restore to. @param device the Device to create the Partition on @param parent the parent PartitionNode @param start start sector of the Partition @param filename name of the image file to restore from */ Partition* RestoreOperation::createRestorePartition(const Device& device, PartitionNode& parent, qint64 start, const QString& filename) { PartitionRole::Roles r = PartitionRole::Primary; if (!parent.isRoot()) r = PartitionRole::Logical; QFileInfo fileInfo(filename); if (!fileInfo.exists()) 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 @@ -1,119 +1,119 @@ /************************************************************************* * 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 .* *************************************************************************/ /** @file */ #include "plugins/dummy/dummybackend.h" #include "plugins/dummy/dummydevice.h" #include "core/diskdevice.h" #include "core/partition.h" #include "core/partitiontable.h" #include "util/globallog.h" #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(DummyBackendFactory, "pmdummybackendplugin.json", registerPlugin();) DummyBackend::DummyBackend(QObject*, const QList&) : CoreBackend() { } void DummyBackend::initFSSupport() { } QList DummyBackend::scanDevices(bool excludeLoop) { Q_UNUSED(excludeLoop) QList result; result.append(scanDevice(QStringLiteral("/dev/sda"))); emitScanProgress(QStringLiteral("/dev/sda"), 100); return result; } Device* DummyBackend::scanDevice(const QString& deviceNode) { DiskDevice* d = new DiskDevice(QStringLiteral("Dummy Device"), QStringLiteral("/tmp") + deviceNode, 255, 30, 63, 512); CoreBackend::setPartitionTableForDevice(*d, new PartitionTable(PartitionTable::msdos_sectorbased, 2048, d->totalSectors() - 2048)); CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), 128); d->partitionTable()->updateUnallocated(*d); d->setIconName(QStringLiteral("drive-harddisk")); CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), 4); return d; } FileSystem::Type DummyBackend::detectFileSystem(const QString& deviceNode) { Q_UNUSED(deviceNode) - return FileSystem::Unknown; + return FileSystem::Type::Unknown; } QString DummyBackend::readLabel(const QString& deviceNode) const { Q_UNUSED(deviceNode) return QString(); } QString DummyBackend::readUUID(const QString& deviceNode) const { Q_UNUSED(deviceNode) return QString(); } std::unique_ptr DummyBackend::openDevice(const Device& d) { std::unique_ptr device = std::make_unique(d.deviceNode()); if (!device->open()) device = nullptr; return device; } std::unique_ptr DummyBackend::openDeviceExclusive(const Device& d) { std::unique_ptr device = std::make_unique(d.deviceNode()); if (!device->openExclusive()) device = nullptr; return device; } bool DummyBackend::closeDevice(std::unique_ptr coreDevice) { return coreDevice->close(); } #include "dummybackend.moc" 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 @@ -1,119 +1,119 @@ /************************************************************************* * Copyright (C) 2010, 2012 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 .* *************************************************************************/ #include "plugins/dummy/dummypartitiontable.h" #include "plugins/dummy/dummybackend.h" #include "core/partition.h" #include "core/device.h" #include "fs/filesystem.h" #include "util/report.h" DummyPartitionTable::DummyPartitionTable() : CoreBackendPartitionTable() { } DummyPartitionTable::~DummyPartitionTable() { } bool DummyPartitionTable::open() { return true; } bool DummyPartitionTable::commit(quint32 timeout) { Q_UNUSED(timeout) return true; } QString DummyPartitionTable::createPartition(Report& report, const Partition& partition) { Q_UNUSED(report) Q_UNUSED(partition) return QStringLiteral("dummy"); } bool DummyPartitionTable::deletePartition(Report& report, const Partition& partition) { Q_UNUSED(report) Q_UNUSED(partition) return true; } bool DummyPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) { Q_UNUSED(report) Q_UNUSED(partition) Q_UNUSED(sector_start) Q_UNUSED(sector_end) return true; } bool DummyPartitionTable::clobberFileSystem(Report& report, const Partition& partition) { Q_UNUSED(report) Q_UNUSED(partition) return true; } bool DummyPartitionTable::resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) { Q_UNUSED(report) Q_UNUSED(partition) Q_UNUSED(newLength) return true; } FileSystem::Type DummyPartitionTable::detectFileSystemBySector(Report& report, const Device& device, qint64 sector) { Q_UNUSED(report) Q_UNUSED(device) Q_UNUSED(sector) - FileSystem::Type rval = FileSystem::Unknown; + FileSystem::Type rval = FileSystem::Type::Unknown; return rval; } bool DummyPartitionTable::setPartitionSystemType(Report& report, const Partition& partition) { Q_UNUSED(report) Q_UNUSED(partition) return true; } bool DummyPartitionTable::setFlag(Report& report, const Partition& partition, PartitionTable::Flag partitionManagerFlag, bool state) { Q_UNUSED(report) Q_UNUSED(partition) Q_UNUSED(partitionManagerFlag) Q_UNUSED(state) return true; } 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 @@ -1,431 +1,431 @@ /************************************************************************* * 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 .* *************************************************************************/ /** @file */ #include "plugins/sfdisk/sfdiskbackend.h" #include "plugins/sfdisk/sfdiskdevice.h" #include "core/diskdevice.h" #include "core/lvmdevice.h" #include "core/partitiontable.h" #include "core/partitionalignment.h" #include "fs/filesystemfactory.h" #include "fs/luks.h" #include "fs/luks2.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(SfdiskBackendFactory, "pmsfdiskbackendplugin.json", registerPlugin();) SfdiskBackend::SfdiskBackend(QObject*, const QList&) : CoreBackend() { } void SfdiskBackend::initFSSupport() { } QList SfdiskBackend::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()); const 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; } /** 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. */ Device* SfdiskBackend::scanDevice(const QString& deviceNode) { ExternalCommand modelCommand(QStringLiteral("lsblk"), { QStringLiteral("--nodeps"), QStringLiteral("--noheadings"), QStringLiteral("--output"), QStringLiteral("model"), deviceNode }); ExternalCommand sizeCommand(QStringLiteral("blockdev"), { QStringLiteral("--getsize64"), 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) ) { QString modelName = modelCommand.output(); modelName = modelName.left(modelName.length() - 1); qint64 deviceSize = sizeCommand.output().trimmed().toLongLong(); Log(Log::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: { // 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); } default: break; } scanDevicePartitions(*d, partitionTable[QLatin1String("partitions")].toArray()); return d; } return nullptr; } /** 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. */ void SfdiskBackend::scanDevicePartitions(Device& d, const QJsonArray& jsonPartitions) { Q_ASSERT(d.partitionTable()); QList partitions; for (const auto &partition : jsonPartitions) { const QJsonObject partitionObject = partition.toObject(); const QString partitionNode = partitionObject[QLatin1String("node")].toString(); const qint64 start = partitionObject[QLatin1String("start")].toVariant().toLongLong(); const qint64 size = partitionObject[QLatin1String("size")].toVariant().toLongLong(); const QString partitionType = partitionObject[QLatin1String("type")].toString(); PartitionTable::Flag activeFlags = partitionObject[QLatin1String("bootable")].toBool() ? PartitionTable::FlagBoot : PartitionTable::FlagNone; if (partitionType == QStringLiteral("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")) activeFlags = PartitionTable::FlagEsp; 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. PartitionNode* parent = d.partitionTable()->findPartitionBySector(start, PartitionRole(PartitionRole::Extended)); // None found, so it's a primary in the device's partition table. if (parent == nullptr) parent = d.partitionTable(); else r = PartitionRole::Logical; FileSystem* fs = FileSystemFactory::create(type, start, start + size - 1, d.logicalSize()); fs->scan(partitionNode); 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(); 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, start, start + size - 1, partitionNode, availableFlags(d.partitionTable()->type()), mountPoint, mounted, activeFlags); if (!part->roles().has(PartitionRole::Luks)) readSectorsUsed(d, *part, mountPoint); if (fs->supportGetLabel() != FileSystem::cmdSupportNone) fs->setLabel(fs->readLabel(part->deviceNode())); if (d.partitionTable()->type() == PartitionTable::TableType::gpt) { part->setLabel(partitionObject[QLatin1String("name")].toString()); part->setUUID(partitionObject[QLatin1String("uuid")].toString()); } 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); } /** 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 */ 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()); } else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportFileSystem) p.fileSystem().setSectorsUsed(p.fileSystem().readUsedCapacity(p.deviceNode()) / d.logicalSize()); } FileSystem::Type SfdiskBackend::detectFileSystem(const QString& partitionPath) { - FileSystem::Type rval = FileSystem::Unknown; + FileSystem::Type rval = FileSystem::Type::Unknown; ExternalCommand udevCommand(QStringLiteral("udevadm"), { QStringLiteral("info"), QStringLiteral("--query=property"), partitionPath }); if (udevCommand.run(-1) && udevCommand.exitCode() == 0) { QRegularExpression re(QStringLiteral("ID_FS_TYPE=(\\w+)")); QRegularExpression re2(QStringLiteral("ID_FS_VERSION=(\\w+)")); QRegularExpressionMatch reFileSystemType = re.match(udevCommand.output()); QRegularExpressionMatch reFileSystemVersion = re2.match(udevCommand.output()); QString s; if (reFileSystemType.hasMatch()) { s = reFileSystemType.captured(1); } QString version; if (reFileSystemVersion.hasMatch()) { 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; } return rval; } QString SfdiskBackend::readLabel(const QString& deviceNode) const { ExternalCommand udevCommand(QStringLiteral("udevadm"), { QStringLiteral("info"), QStringLiteral("--query=property"), deviceNode }); udevCommand.run(); QRegularExpression re(QStringLiteral("ID_FS_LABEL=(.*)")); QRegularExpressionMatch reFileSystemLabel = re.match(udevCommand.output()); if (reFileSystemLabel.hasMatch()) return reFileSystemLabel.captured(1); return QString(); } QString SfdiskBackend::readUUID(const QString& deviceNode) const { ExternalCommand udevCommand(QStringLiteral("udevadm"), { QStringLiteral("info"), QStringLiteral("--query=property"), deviceNode }); udevCommand.run(); QRegularExpression re(QStringLiteral("ID_FS_UUID=(.*)")); QRegularExpressionMatch reFileSystemUUID = re.match(udevCommand.output()); if (reFileSystemUUID.hasMatch()) return reFileSystemUUID.captured(1); return QString(); } PartitionTable::Flags SfdiskBackend::availableFlags(PartitionTable::TableType type) { PartitionTable::Flags flags; if (type == PartitionTable::gpt) { // These are not really flags but for now keep them for compatibility // We should implement changing partition type flags = PartitionTable::FlagBiosGrub | PartitionTable::FlagEsp; } else if (type == PartitionTable::msdos || type == PartitionTable::msdos_sectorbased) flags = PartitionTable::FlagBoot; return flags; } std::unique_ptr SfdiskBackend::openDevice(const Device& d) { std::unique_ptr device = std::make_unique(d); if (!device->open()) device = nullptr; return device; } std::unique_ptr SfdiskBackend::openDeviceExclusive(const Device& d) { std::unique_ptr device = std::make_unique(d); if (!device->openExclusive()) device = nullptr; return device; } bool SfdiskBackend::closeDevice(std::unique_ptr coreDevice) { return coreDevice->close(); } #include "sfdiskbackend.moc" 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 @@ -1,254 +1,254 @@ /************************************************************************* * 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 "plugins/sfdisk/sfdiskpartitiontable.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 #include #include #include #include SfdiskPartitionTable::SfdiskPartitionTable(const Device* d) : CoreBackendPartitionTable(), m_device(d) { } SfdiskPartitionTable::~SfdiskPartitionTable() { } bool SfdiskPartitionTable::open() { return true; } 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); return true; } QString SfdiskPartitionTable::createPartition(Report& report, const Partition& partition) { if ( !(partition.roles().has(PartitionRole::Extended) || partition.roles().has(PartitionRole::Logical) || partition.roles().has(PartitionRole::Primary) ) ) { report.line() << xi18nc("@info:progress", "Unknown partition role for new partition %1 (roles: %2)", partition.deviceNode(), partition.roles().toString()); return QString(); } QByteArray type = QByteArray(); if (partition.roles().has(PartitionRole::Extended)) type = QByteArrayLiteral(" type=5"); // NOTE: at least on GPT partition types "are" partition flags 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() ) { QRegularExpression re(QStringLiteral("Created a new partition (\\d)")); QRegularExpressionMatch rem = re.match(createCommand.output()); if (rem.hasMatch()) return partition.devicePath() + rem.captured(1); } report.line() << xi18nc("@info:progress", "Failed to add partition %1 to device %2.", partition.deviceNode(), m_device->deviceNode()); return QString(); } bool SfdiskPartitionTable::deletePartition(Report& report, const Partition& partition) { ExternalCommand deleteCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--force"), QStringLiteral("--delete"), partition.devicePath(), QString::number(partition.number()) } ); if (deleteCommand.run(-1) && deleteCommand.exitCode() == 0) return true; report.line() << xi18nc("@info:progress", "Could not delete partition %1.", partition.devicePath()); return false; } 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.write(QByteArrayLiteral("start=") + QByteArray::number(sectorStart) + QByteArrayLiteral(" size=") + QByteArray::number(sectorEnd - sectorStart + 1) + QByteArrayLiteral("\nY\n")) && sfdiskCommand.start(-1) && sfdiskCommand.waitFor() && sfdiskCommand.exitCode() == 0) { return true; } report.line() << xi18nc("@info:progress", "Could not set geometry for partition %1 while trying to resize/move it.", partition.devicePath()); return false; } bool SfdiskPartitionTable::clobberFileSystem(Report& report, const Partition& partition) { ExternalCommand wipeCommand(report, QStringLiteral("wipefs"), { QStringLiteral("--all"), partition.partitionPath() } ); if (wipeCommand.run(-1) && wipeCommand.exitCode() == 0) return true; report.line() << xi18nc("@info:progress", "Failed to erase filesystem signature on partition %1.", partition.partitionPath()); return false; } bool SfdiskPartitionTable::resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) { // sfdisk does not have any partition resize capabilities Q_UNUSED(report) Q_UNUSED(partition) Q_UNUSED(newLength) return false; } 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) { const QJsonArray partitionTable = QJsonDocument::fromJson(jsonCommand.rawOutput()).object()[QLatin1String("partitiontable")].toObject()[QLatin1String("partitions")].toArray(); for (const auto &partition : partitionTable) { const QJsonObject partitionObject = partition.toObject(); const qint64 start = partitionObject[QLatin1String("start")].toVariant().toLongLong(); if (start == sector) { const QString deviceNode = partitionObject[QLatin1String("node")].toString(); type = CoreBackendManager::self()->backend()->detectFileSystem(deviceNode); return type; } } } report.line() << xi18nc("@info:progress", "Could not determine file system of partition at sector %1 on device %2.", sector, device.deviceNode()); return type; } 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 }; static QLatin1String getPartitionType(FileSystem::Type t, PartitionTable::TableType tableType) { quint8 type; switch (tableType) { case PartitionTable::gpt: type = 0; break; case PartitionTable::msdos: case PartitionTable::msdos_sectorbased: type = 1; break; default:; return QLatin1String(); } for (quint32 i = 0; i < sizeof(typemap) / sizeof(typemap[0]); i++) if (typemap[i].type == t) return typemap[i].partitionType[type]; return QLatin1String(); } bool SfdiskPartitionTable::setPartitionSystemType(Report& report, const Partition& partition) { QString partitionType = getPartitionType(partition.fileSystem().type(), m_device->partitionTable()->type()); if (partitionType.isEmpty()) return true; ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--part-type"), m_device->deviceNode(), QString::number(partition.number()), partitionType } ); return sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0; } bool SfdiskPartitionTable::setFlag(Report& report, const Partition& partition, PartitionTable::Flag flag, bool state) { // We only allow setting one active partition per device if (flag == PartitionTable::FlagBoot && state == true) { ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--activate"), m_device->deviceNode(), QString::number(partition.number()) } ); if (sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0) return true; else return false; } else if (flag == PartitionTable::FlagBoot && state == false) { ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--activate"), m_device->deviceNode(), QStringLiteral("-") } ); if (sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0) return true; // FIXME: Do not return false since we have no way of checking if partition table is MBR } if (flag == PartitionTable::FlagEsp && state == true) { ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--part-type"), m_device->deviceNode(), QString::number(partition.number()), QStringLiteral("C12A7328-F81F-11D2-BA4B-00A0C93EC93B") } ); if (sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0) return true; else return false; } if (flag == PartitionTable::FlagEsp && state == false) setPartitionSystemType(report, partition); if (flag == PartitionTable::FlagBiosGrub && state == true) { ExternalCommand sfdiskCommand(report, QStringLiteral("sfdisk"), { QStringLiteral("--part-type"), m_device->deviceNode(), QString::number(partition.number()), QStringLiteral("21686148-6449-6E6F-744E-656564454649") } ); if (sfdiskCommand.run(-1) && sfdiskCommand.exitCode() == 0) return true; else return false; } if (flag == PartitionTable::FlagBiosGrub && state == false) setPartitionSystemType(report, partition); return true; }