2015-06-04 01:29:22 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* Copyright (C) 2008-2012 by Volker Lanz <vl@fidra.de> *
|
2016-03-31 17:43:38 +01:00
|
|
|
* Copyright (C) 2015-2016 by Teo Mrnjavac <teo@kde.org> *
|
2016-03-02 19:00:31 +00:00
|
|
|
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
|
2015-06-04 01:29:22 +01:00
|
|
|
* *
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.*
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "plugins/libparted/libpartedbackend.h"
|
|
|
|
#include "plugins/libparted/libparteddevice.h"
|
2016-07-21 13:16:29 +01:00
|
|
|
#include "plugins/libparted/pedflags.h"
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-05-31 19:28:31 +01:00
|
|
|
#include "core/diskdevice.h"
|
2015-06-04 01:29:22 +01:00
|
|
|
#include "core/partition.h"
|
|
|
|
#include "core/partitiontable.h"
|
|
|
|
#include "core/partitionalignment.h"
|
|
|
|
|
|
|
|
#include "fs/filesystem.h"
|
|
|
|
#include "fs/filesystemfactory.h"
|
|
|
|
|
|
|
|
#include "fs/fat16.h"
|
|
|
|
#include "fs/hfs.h"
|
|
|
|
#include "fs/hfsplus.h"
|
|
|
|
#include "fs/luks.h"
|
2016-05-23 11:29:33 +01:00
|
|
|
#include "fs/lvm2_pv.h"
|
2015-06-04 01:29:22 +01:00
|
|
|
|
|
|
|
#include "util/globallog.h"
|
2016-07-22 12:56:59 +01:00
|
|
|
#include "util/externalcommand.h"
|
2015-06-04 01:29:22 +01:00
|
|
|
#include "util/helpers.h"
|
|
|
|
|
2016-07-29 18:15:28 +01:00
|
|
|
#include <blkid/blkid.h>
|
|
|
|
|
2016-05-09 11:07:31 +01:00
|
|
|
#include <QDebug>
|
2015-06-04 01:29:22 +01:00
|
|
|
#include <QString>
|
|
|
|
#include <QStringList>
|
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
#include <KAuth>
|
2015-06-04 01:29:22 +01:00
|
|
|
#include <KLocalizedString>
|
2016-05-22 00:48:55 +01:00
|
|
|
#include <KMountPoint>
|
|
|
|
#include <KDiskFreeSpaceInfo>
|
2015-06-04 01:29:22 +01:00
|
|
|
#include <KPluginFactory>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
K_PLUGIN_FACTORY_WITH_JSON(LibPartedBackendFactory, "pmlibpartedbackendplugin.json", registerPlugin<LibPartedBackend>();)
|
|
|
|
|
|
|
|
static QString s_lastPartedExceptionMessage;
|
|
|
|
|
|
|
|
/** Callback to handle exceptions from libparted
|
2015-07-13 15:16:36 +01:00
|
|
|
@param e the libparted exception to handle
|
2015-06-04 01:29:22 +01:00
|
|
|
*/
|
|
|
|
static PedExceptionOption pedExceptionHandler(PedException* e)
|
|
|
|
{
|
2016-07-17 23:41:00 +01:00
|
|
|
Log(Log::error) << xi18nc("@info:status", "LibParted Exception: %1", QString::fromLocal8Bit(e->message));
|
2015-07-13 15:16:36 +01:00
|
|
|
s_lastPartedExceptionMessage = QString::fromLocal8Bit(e->message);
|
|
|
|
return PED_EXCEPTION_UNHANDLED;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Reads sectors used on a FileSystem using libparted functions.
|
2015-07-13 15:16:36 +01:00
|
|
|
@param pedDisk pointer to pedDisk where the Partition and its FileSystem are
|
|
|
|
@param p the Partition the FileSystem is on
|
|
|
|
@return the number of sectors used
|
2015-06-04 01:29:22 +01:00
|
|
|
*/
|
|
|
|
#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT
|
2016-07-21 13:16:29 +01:00
|
|
|
static qint64 readSectorsUsedLibParted(const Partition& p)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2016-07-25 16:29:02 +01:00
|
|
|
KAuth::Action action = QStringLiteral("org.kde.kpmcore.scan.readsectorsused");
|
|
|
|
action.setHelperId(QStringLiteral("org.kde.kpmcore.scan"));
|
2016-07-29 14:17:36 +01:00
|
|
|
QVariantMap args = {
|
|
|
|
{ QStringLiteral("deviceNode"), p.deviceNode() },
|
|
|
|
{ QStringLiteral("firstSector"), p.firstSector() }
|
|
|
|
};
|
2016-07-25 16:29:02 +01:00
|
|
|
action.setArguments(args);
|
|
|
|
KAuth::ExecuteJob *job = action.execute();
|
2016-07-21 13:16:29 +01:00
|
|
|
if (!job->exec()) {
|
|
|
|
qWarning() << "KAuth returned an error code: " << job->errorString();
|
|
|
|
return -1;
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
return job->data()[QLatin1String("sectorsUsed")].toLongLong();
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** Reads the sectors used in a FileSystem and stores the result in the Partition's FileSystem object.
|
2015-07-13 15:16:36 +01:00
|
|
|
@param p the Partition the FileSystem is on
|
|
|
|
@param mountPoint mount point of the partition in question
|
2015-06-04 01:29:22 +01:00
|
|
|
*/
|
2016-05-31 19:28:31 +01:00
|
|
|
static void readSectorsUsed(const DiskDevice& d, Partition& p, const QString& mountPoint)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-04-26 13:53:25 +01:00
|
|
|
if (p.isMounted() && freeSpaceInfo.isValid() && mountPoint != QString())
|
2015-07-13 15:16:36 +01:00
|
|
|
p.fileSystem().setSectorsUsed(freeSpaceInfo.used() / d.logicalSectorSize());
|
|
|
|
else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportFileSystem)
|
|
|
|
p.fileSystem().setSectorsUsed(p.fileSystem().readUsedCapacity(p.deviceNode()) / d.logicalSectorSize());
|
2015-06-04 01:29:22 +01:00
|
|
|
#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT
|
2016-07-21 13:16:29 +01:00
|
|
|
else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportBackend)
|
|
|
|
p.fileSystem().setSectorsUsed(readSectorsUsedLibParted(p));
|
2015-06-04 01:29:22 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Constructs a LibParted object. */
|
|
|
|
LibPartedBackend::LibPartedBackend(QObject*, const QList<QVariant>&) :
|
2015-07-13 15:16:36 +01:00
|
|
|
CoreBackend()
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
ped_exception_set_handler(pedExceptionHandler);
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void LibPartedBackend::initFSSupport()
|
|
|
|
{
|
|
|
|
#if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::fat16::m_Shrink == FileSystem::cmdSupportNone)
|
|
|
|
FS::fat16::m_Shrink = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::fat16::m_Grow == FileSystem::cmdSupportNone)
|
|
|
|
FS::fat16::m_Grow = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::hfs::m_Shrink == FileSystem::cmdSupportNone)
|
|
|
|
FS::hfs::m_Shrink = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::hfsplus::m_Shrink == FileSystem::cmdSupportNone)
|
|
|
|
FS::hfsplus::m_Shrink = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::hfs::m_GetUsed == FileSystem::cmdSupportNone)
|
|
|
|
FS::hfs::m_GetUsed = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (FS::hfsplus::m_GetUsed == FileSystem::cmdSupportNone)
|
|
|
|
FS::hfsplus::m_GetUsed = FileSystem::cmdSupportBackend;
|
2015-06-04 01:29:22 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
/** Create a Device for the given deviceNode and scan it for partitions.
|
|
|
|
@param deviceNode the device node (e.g. "/dev/sda")
|
|
|
|
@return the created Device object. callers need to free this.
|
2015-06-04 01:29:22 +01:00
|
|
|
*/
|
2016-07-21 13:16:29 +01:00
|
|
|
Device* LibPartedBackend::scanDevice(const QString& deviceNode)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2016-07-21 13:16:29 +01:00
|
|
|
KAuth::Action scanAction = QStringLiteral("org.kde.kpmcore.scan.scandevice");
|
|
|
|
scanAction.setHelperId(QStringLiteral("org.kde.kpmcore.scan"));
|
2016-07-29 14:17:36 +01:00
|
|
|
QVariantMap args = {{ QStringLiteral("deviceNode"), deviceNode }};
|
2016-07-21 13:16:29 +01:00
|
|
|
scanAction.setArguments(args);
|
|
|
|
KAuth::ExecuteJob *job = scanAction.execute();
|
|
|
|
if (!job->exec()) {
|
|
|
|
qWarning() << "KAuth returned an error code: " << job->errorString();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool pedDeviceError = job->data()[QLatin1String("pedDeviceError")].toBool();
|
|
|
|
|
|
|
|
if (pedDeviceError) {
|
|
|
|
Log(Log::warning) << xi18nc("@info:status", "Could not access device <filename>%1</filename>", deviceNode);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString model = job->data()[QLatin1String("model")].toString();
|
|
|
|
QString path = job->data()[QLatin1String("path")].toString();
|
|
|
|
int heads = job->data()[QLatin1String("heads")].toInt();
|
|
|
|
int sectors = job->data()[QLatin1String("sectors")].toInt();
|
|
|
|
int cylinders = job->data()[QLatin1String("cylinders")].toInt();
|
|
|
|
int sectorSize = job->data()[QLatin1String("sectorSize")].toInt();
|
|
|
|
bool pedDiskError = job->data()[QLatin1String("pedDiskError")].toBool();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
Log(Log::information) << xi18nc("@info:status", "Device found: %1", model);
|
|
|
|
|
2016-05-31 19:28:31 +01:00
|
|
|
DiskDevice* d = new DiskDevice(model, path, heads, sectors, cylinders, sectorSize);
|
2016-07-21 13:16:29 +01:00
|
|
|
|
|
|
|
if (pedDiskError)
|
|
|
|
return d;
|
|
|
|
|
|
|
|
QString typeName = job->data()[QLatin1String("typeName")].toString();
|
|
|
|
qint32 maxPrimaryPartitionCount = job->data()[QLatin1String("maxPrimaryPartitionCount")].toInt();
|
|
|
|
quint64 firstUsableSector = job->data()[QLatin1String("firstUsableSector")].toULongLong();
|
|
|
|
quint64 lastUsableSector = job->data()[QLatin1String("lastUsableSector")].toULongLong();
|
|
|
|
|
|
|
|
const PartitionTable::TableType type = PartitionTable::nameToTableType(typeName);
|
|
|
|
CoreBackend::setPartitionTableForDevice(*d, new PartitionTable(type, firstUsableSector, lastUsableSector));
|
|
|
|
CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), maxPrimaryPartitionCount);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
|
|
|
|
mountPoints.append(KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName));
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
QList<QVariant> partitionPath = job->data()[QLatin1String("partitionPath")].toList();
|
|
|
|
QList<QVariant> partitionType = job->data()[QLatin1String("partitionType")].toList();
|
|
|
|
QList<QVariant> partitionStart = job->data()[QLatin1String("partitionStart")].toList();
|
|
|
|
QList<QVariant> partitionEnd = job->data()[QLatin1String("partitionEnd")].toList();
|
|
|
|
QList<QVariant> partitionBusy = job->data()[QLatin1String("partitionBusy")].toList();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
quint32 totalPartitions = partitionPath.size();
|
|
|
|
QList<Partition*> partitions;
|
|
|
|
for (quint32 i = 0; i < totalPartitions; ++i) {
|
|
|
|
QString partitionNode = partitionPath[i].toString();
|
|
|
|
int type = partitionType[i].toInt();
|
|
|
|
qint64 start = partitionStart[i].toLongLong();
|
|
|
|
qint64 end = partitionEnd[i].toLongLong();
|
|
|
|
bool busy = partitionBusy[i].toBool();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
PartitionRole::Roles r = PartitionRole::None;
|
2016-05-06 19:14:01 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
FileSystem::Type fsType = detectFileSystem(partitionNode);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
switch (type) {
|
2015-07-13 15:16:36 +01:00
|
|
|
case PED_PARTITION_NORMAL:
|
|
|
|
r = PartitionRole::Primary;
|
|
|
|
break;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
case PED_PARTITION_EXTENDED:
|
|
|
|
r = PartitionRole::Extended;
|
|
|
|
type = FileSystem::Extended;
|
|
|
|
break;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
case PED_PARTITION_LOGICAL:
|
|
|
|
r = PartitionRole::Logical;
|
|
|
|
break;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
// Find an extended partition this partition is in.
|
2016-07-21 13:16:29 +01:00
|
|
|
PartitionNode* parent = d->partitionTable()->findPartitionBySector(start, PartitionRole(PartitionRole::Extended));
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
// None found, so it's a primary in the device's partition table.
|
2015-07-22 14:48:03 +01:00
|
|
|
if (parent == nullptr)
|
2016-07-21 13:16:29 +01:00
|
|
|
parent = d->partitionTable();
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
FileSystem* fs = FileSystemFactory::create(fsType, start, end);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
// libparted does not handle LUKS partitions
|
|
|
|
QString mountPoint;
|
2015-09-10 13:47:50 +01:00
|
|
|
bool mounted = false;
|
2016-07-21 13:16:29 +01:00
|
|
|
if (fsType == FileSystem::Luks) {
|
2016-04-19 15:46:18 +01:00
|
|
|
r |= PartitionRole::Luks;
|
2016-08-05 13:55:56 +01:00
|
|
|
FS::luks* luksFs = static_cast<FS::luks*>(fs);
|
2016-07-21 13:16:29 +01:00
|
|
|
QString mapperNode = FS::luks::mapperName(partitionNode);
|
2015-09-10 13:47:50 +01:00
|
|
|
bool isCryptOpen = !mapperNode.isEmpty();
|
|
|
|
luksFs->setCryptOpen(isCryptOpen);
|
2016-07-21 13:16:29 +01:00
|
|
|
luksFs->setLogicalSectorSize(d->logicalSectorSize());
|
2015-09-10 13:47:50 +01:00
|
|
|
|
|
|
|
if (isCryptOpen) {
|
2016-07-21 13:16:29 +01:00
|
|
|
luksFs->loadInnerFileSystem(partitionNode, mapperNode);
|
2016-04-13 17:32:21 +01:00
|
|
|
|
2016-05-23 11:29:33 +01:00
|
|
|
if (luksFs->type() == FileSystem::Lvm2_PV) {
|
|
|
|
mountPoint = FS::lvm2_pv::getVGName(mapperNode);
|
|
|
|
mounted = false;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
mountPoint = mountPoints.findByDevice(mapperNode) ?
|
|
|
|
mountPoints.findByDevice(mapperNode)->mountPoint() :
|
|
|
|
QString();
|
|
|
|
// We cannot use libparted to check the mounted status because
|
|
|
|
// we don't have a PedPartition for the mapper device, so we use lsblk
|
|
|
|
mounted = isMounted(mapperNode);
|
|
|
|
}
|
2016-05-22 00:52:07 +01:00
|
|
|
if (mounted) {
|
|
|
|
const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint);
|
|
|
|
if (freeSpaceInfo.isValid() && mountPoint != QString())
|
2016-07-23 13:28:46 +01:00
|
|
|
luksFs->setSectorsUsed((freeSpaceInfo.used() + luksFs->getPayloadOffset(partitionNode)) / d->logicalSectorSize());
|
2016-05-22 00:52:07 +01:00
|
|
|
}
|
2015-09-10 13:47:50 +01:00
|
|
|
} else {
|
|
|
|
mounted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
luksFs->setMounted(mounted);
|
2016-05-23 11:29:33 +01:00
|
|
|
} else if (type == FileSystem::Lvm2_PV) {
|
|
|
|
//TODO: adding PartitionRole
|
2016-05-31 19:28:31 +01:00
|
|
|
mountPoint = FS::lvm2_pv::getVGName(partitionNode);
|
2016-05-23 11:29:33 +01:00
|
|
|
mounted = false;
|
2015-07-13 15:16:36 +01:00
|
|
|
} else {
|
2016-07-21 13:16:29 +01:00
|
|
|
mountPoint = mountPoints.findByDevice(partitionNode) ?
|
|
|
|
mountPoints.findByDevice(partitionNode)->mountPoint() :
|
2015-09-10 13:47:50 +01:00
|
|
|
QString();
|
2016-07-21 13:16:29 +01:00
|
|
|
mounted = busy;
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-29 18:15:28 +01:00
|
|
|
QList<QVariant> availableFlags = job->data()[QLatin1String("availableFlags")].toList();
|
2016-07-21 13:16:29 +01:00
|
|
|
PartitionTable::Flags available = static_cast<PartitionTable::Flag>(availableFlags[i].toInt());
|
2016-07-29 18:15:28 +01:00
|
|
|
QList<QVariant> activeFlags = job->data()[QLatin1String("activeFlags")].toList();
|
2016-07-21 13:16:29 +01:00
|
|
|
PartitionTable::Flags active = static_cast<PartitionTable::Flag>(activeFlags[i].toInt());
|
|
|
|
Partition* part = new Partition(parent, *d, PartitionRole(r), fs, start, end, partitionNode, available, mountPoint, mounted, active);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-05-22 00:48:55 +01:00
|
|
|
if (!part->roles().has(PartitionRole::Luks))
|
2016-07-21 13:16:29 +01:00
|
|
|
readSectorsUsed(*d, *part, mountPoint);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (fs->supportGetLabel() != FileSystem::cmdSupportNone)
|
|
|
|
fs->setLabel(fs->readLabel(part->deviceNode()));
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
if (fs->supportGetUUID() != FileSystem::cmdSupportNone)
|
|
|
|
fs->setUUID(fs->readUUID(part->deviceNode()));
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
parent->append(part);
|
|
|
|
partitions.append(part);
|
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
d->partitionTable()->updateUnallocated(*d);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
if (d->partitionTable()->isSectorBased(*d))
|
|
|
|
d->partitionTable()->setType(*d, PartitionTable::msdos_sectorbased);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
foreach(const Partition * part, partitions)
|
2016-07-21 13:16:29 +01:00
|
|
|
PartitionAlignment::isAligned(*d, *part);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
return d;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
2016-07-23 22:01:38 +01:00
|
|
|
QList<Device*> LibPartedBackend::scanDevices(bool excludeReadOnly)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
QList<Device*> result;
|
2016-07-23 22:01:38 +01:00
|
|
|
// FIXME: cat /sys/block/loop0/ro
|
|
|
|
// linux.git/tree/Documentation/devices.txt
|
|
|
|
QString blockDeviceMajorNumbers = QStringLiteral(
|
|
|
|
"3,22,33,34,56,57,88,89,90,91,128,129,130,131,132,133,134,135," // MFM, RLL and IDE hard disk/CD-ROM interface
|
|
|
|
"7," // loop devices
|
|
|
|
"8,65,66,67,68,69,70,71," // SCSI disk devices
|
|
|
|
"80,81,82,83,84,85,86,87," // I2O hard disk
|
|
|
|
"179," // MMC block devices
|
|
|
|
"259" // Block Extended Major (include NVMe)
|
|
|
|
);
|
2016-07-22 12:56:59 +01:00
|
|
|
ExternalCommand cmd(QStringLiteral("lsblk"), {
|
|
|
|
QStringLiteral("--nodeps"),
|
|
|
|
QStringLiteral("--noheadings"),
|
|
|
|
QStringLiteral("--output"), QString::fromLatin1("name"),
|
|
|
|
QStringLiteral("--paths"),
|
2016-07-23 22:01:38 +01:00
|
|
|
QStringLiteral("--include"), blockDeviceMajorNumbers});
|
2016-07-22 12:56:59 +01:00
|
|
|
if (cmd.run(-1) && cmd.exitCode() == 0) {
|
|
|
|
QStringList devices = cmd.output().split(QString::fromLatin1("\n"));
|
|
|
|
devices.removeLast();
|
|
|
|
quint32 totalDevices = devices.length();
|
|
|
|
for (quint32 i = 0; i < totalDevices; ++i) {
|
2016-07-23 22:01:38 +01:00
|
|
|
if (excludeReadOnly) {
|
|
|
|
QFile f(QStringLiteral("/sys/block/%1/ro").arg(QString(devices[i]).remove(QStringLiteral("/dev/"))));
|
|
|
|
if (f.open(QIODevice::ReadOnly))
|
|
|
|
if (f.readLine().trimmed().toInt() == 1)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-07-22 12:56:59 +01:00
|
|
|
emitScanProgress(devices[i], i * 100 / totalDevices);
|
|
|
|
result.append(scanDevice(devices[i]));
|
|
|
|
}
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
2016-05-06 19:14:01 +01:00
|
|
|
/** Detects the type of a FileSystem given a PedDevice and a PedPartition
|
2016-07-29 18:15:28 +01:00
|
|
|
@param partitionPath path to the partition
|
2016-05-06 19:14:01 +01:00
|
|
|
@return the detected FileSystem type (FileSystem::Unknown if not detected)
|
|
|
|
*/
|
2016-07-29 18:15:28 +01:00
|
|
|
FileSystem::Type LibPartedBackend::detectFileSystem(const QString& partitionPath)
|
2016-05-06 19:14:01 +01:00
|
|
|
{
|
|
|
|
FileSystem::Type rval = FileSystem::Unknown;
|
|
|
|
|
2016-07-29 18:15:28 +01:00
|
|
|
blkid_cache cache;
|
|
|
|
if (blkid_get_cache(&cache, nullptr) == 0) {
|
|
|
|
blkid_dev dev;
|
|
|
|
|
|
|
|
if ((dev = blkid_get_dev(cache,
|
|
|
|
partitionPath.toLocal8Bit().constData(),
|
|
|
|
BLKID_DEV_NORMAL)) != nullptr) {
|
|
|
|
char *string = blkid_get_tag_value(cache, "TYPE", partitionPath.toLocal8Bit().constData());
|
|
|
|
QString s = QString::fromUtf8(string);
|
|
|
|
free(string);
|
|
|
|
|
|
|
|
if (s == QStringLiteral("ext2")) rval = FileSystem::Ext2;
|
|
|
|
else if (s == QStringLiteral("ext3")) rval = FileSystem::Ext3;
|
|
|
|
else if (s.startsWith(QStringLiteral("ext4"))) rval = FileSystem::Ext4;
|
|
|
|
else if (s == QStringLiteral("swap")) rval = FileSystem::LinuxSwap;
|
|
|
|
else if (s == QStringLiteral("ntfs")) rval = FileSystem::Ntfs;
|
|
|
|
else if (s == QStringLiteral("reiserfs")) rval = FileSystem::ReiserFS;
|
|
|
|
else if (s == QStringLiteral("reiser4")) rval = FileSystem::Reiser4;
|
|
|
|
else if (s == QStringLiteral("xfs")) rval = FileSystem::Xfs;
|
|
|
|
else if (s == QStringLiteral("jfs")) rval = FileSystem::Jfs;
|
|
|
|
else if (s == QStringLiteral("hfs")) rval = FileSystem::Hfs;
|
|
|
|
else if (s == QStringLiteral("hfsplus")) rval = FileSystem::HfsPlus;
|
|
|
|
else if (s == QStringLiteral("ufs")) rval = FileSystem::Ufs;
|
|
|
|
else if (s == QStringLiteral("vfat")) {
|
|
|
|
// libblkid uses SEC_TYPE to distinguish between FAT16 and FAT32
|
|
|
|
string = blkid_get_tag_value(cache, "SEC_TYPE", partitionPath.toLocal8Bit().constData());
|
|
|
|
QString st = QString::fromUtf8(string);
|
|
|
|
free(string);
|
|
|
|
if (st == QStringLiteral("msdos"))
|
|
|
|
rval = FileSystem::Fat16;
|
|
|
|
else
|
|
|
|
rval = FileSystem::Fat32;
|
|
|
|
} else if (s == QStringLiteral("btrfs")) rval = FileSystem::Btrfs;
|
|
|
|
else if (s == QStringLiteral("ocfs2")) rval = FileSystem::Ocfs2;
|
|
|
|
else if (s == QStringLiteral("zfs_member")) rval = FileSystem::Zfs;
|
|
|
|
else if (s == QStringLiteral("hpfs")) rval = FileSystem::Hpfs;
|
|
|
|
else if (s == QStringLiteral("crypto_LUKS")) rval = FileSystem::Luks;
|
|
|
|
else if (s == QStringLiteral("exfat")) rval = FileSystem::Exfat;
|
|
|
|
else if (s == QStringLiteral("nilfs2")) rval = FileSystem::Nilfs2;
|
|
|
|
else if (s == QStringLiteral("LVM2_member")) rval = FileSystem::Lvm2_PV;
|
|
|
|
else if (s == QStringLiteral("f2fs")) rval = FileSystem::F2fs;
|
|
|
|
else
|
|
|
|
qWarning() << "blkid: unknown file system type " << s << " on " << partitionPath;
|
|
|
|
}
|
2016-07-29 14:17:36 +01:00
|
|
|
|
2016-07-29 18:15:28 +01:00
|
|
|
blkid_put_cache(cache);
|
2016-07-24 21:36:56 +01:00
|
|
|
}
|
2016-05-06 19:14:01 +01:00
|
|
|
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
CoreBackendDevice* LibPartedBackend::openDevice(const QString& deviceNode)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2016-07-21 13:16:29 +01:00
|
|
|
LibPartedDevice* device = new LibPartedDevice(deviceNode);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-22 14:48:03 +01:00
|
|
|
if (device == nullptr || !device->open()) {
|
2015-07-13 15:16:36 +01:00
|
|
|
delete device;
|
2015-07-22 14:48:03 +01:00
|
|
|
device = nullptr;
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
return device;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
2016-07-21 13:16:29 +01:00
|
|
|
CoreBackendDevice* LibPartedBackend::openDeviceExclusive(const QString& deviceNode)
|
2015-06-04 01:29:22 +01:00
|
|
|
{
|
2016-07-21 13:16:29 +01:00
|
|
|
LibPartedDevice* device = new LibPartedDevice(deviceNode);
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-22 14:48:03 +01:00
|
|
|
if (device == nullptr || !device->openExclusive()) {
|
2015-07-13 15:16:36 +01:00
|
|
|
delete device;
|
2015-07-22 14:48:03 +01:00
|
|
|
device = nullptr;
|
2015-07-13 15:16:36 +01:00
|
|
|
}
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
return device;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool LibPartedBackend::closeDevice(CoreBackendDevice* core_device)
|
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
return core_device->close();
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PedPartitionFlag LibPartedBackend::getPedFlag(PartitionTable::Flag flag)
|
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
for (quint32 i = 0; i < sizeof(flagmap) / sizeof(flagmap[0]); i++)
|
|
|
|
if (flagmap[i].flag == flag)
|
|
|
|
return flagmap[i].pedFlag;
|
2015-06-04 01:29:22 +01:00
|
|
|
|
2015-07-13 15:16:36 +01:00
|
|
|
return static_cast<PedPartitionFlag>(-1);
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QString LibPartedBackend::lastPartedExceptionMessage()
|
|
|
|
{
|
2015-07-13 15:16:36 +01:00
|
|
|
return s_lastPartedExceptionMessage;
|
2015-06-04 01:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#include "libpartedbackend.moc"
|