diff --git a/CMakeLists.txt b/CMakeLists.txt index 47c22bb..5782ad1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,6 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS # Load the frameworks we need find_package(KF5 REQUIRED - Auth I18n IconThemes KIO diff --git a/src/plugins/libparted/CMakeLists.txt b/src/plugins/libparted/CMakeLists.txt index dee60c0..2af8986 100644 --- a/src/plugins/libparted/CMakeLists.txt +++ b/src/plugins/libparted/CMakeLists.txt @@ -39,5 +39,3 @@ target_link_libraries(pmlibpartedbackendplugin kpmcore ${LIBPARTED_LIBS} KF5::Au install(TARGETS pmlibpartedbackendplugin DESTINATION ${KDE_INSTALL_PLUGINDIR}) kcoreaddons_desktop_to_json(pmlibpartedbackendplugin pmlibpartedbackendplugin.desktop DEFAULT_SERVICE_TYPE) install(FILES pmlibpartedbackendplugin.desktop DESTINATION ${SERVICES_INSTALL_DIR}) - -add_subdirectory(helpers) diff --git a/src/plugins/libparted/helpers/CMakeLists.txt b/src/plugins/libparted/helpers/CMakeLists.txt deleted file mode 100644 index fe13dd7..0000000 --- a/src/plugins/libparted/helpers/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_executable(kpmcore_scan scan.cpp) -target_link_libraries(kpmcore_scan ${LIBPARTED_LIBS} KF5::Auth) -install(TARGETS kpmcore_scan DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) - -kauth_install_helper_files(kpmcore_scan org.kde.kpmcore.scan root) -kauth_install_actions(org.kde.kpmcore.scan org.kde.kpmcore.scan.actions) diff --git a/src/plugins/libparted/helpers/org.kde.kpmcore.scan.actions b/src/plugins/libparted/helpers/org.kde.kpmcore.scan.actions deleted file mode 100644 index cd3b373..0000000 --- a/src/plugins/libparted/helpers/org.kde.kpmcore.scan.actions +++ /dev/null @@ -1,79 +0,0 @@ -[org.kde.kpmcore.scan.scandevice] -Name=Scan device action -Name[ca]=Acció de dispositiu d'escàner -Name[ca@valencia]=Acció de dispositiu d'escàner -Name[en_GB]=Scan device action -Name[es]=Acción de explorar dispositivos -Name[lt]=Įrenginio skenavimo veiksmas -Name[nl]=Actie Apparaat scannen -Name[pl]=Działanie przeszukiwania urządzenia -Name[pt]=Acção para analisar o dispositivo -Name[sl]=Dejanje preiskovanja naprave -Name[sr]=Радња скенирања уређаја -Name[sr@ijekavian]=Радња скенирања уређаја -Name[sr@ijekavianlatin]=Radnja skeniranja uređaja -Name[sr@latin]=Radnja skeniranja uređaja -Name[sv]=Alternativ för att söka igenom enhet -Name[uk]=Дія зі сканування пристрою -Name[x-test]=xxScan device actionxx -Name[zh_TW]=掃描裝置動作 -Description=Scan device -Description[ca]=Dispositiu d'escàner -Description[ca@valencia]=Dispositiu d'escàner -Description[en_GB]=Scan device -Description[es]=Explorar dispositivos -Description[lt]=Skenuoti įrenginį -Description[nl]=Apparaat scannen -Description[pl]=Przeszukaj urządzenie -Description[pt]=Analisar o dispositivo -Description[sl]=Preišči napravo -Description[sr]=Скенирање уређаја -Description[sr@ijekavian]=Скенирање уређаја -Description[sr@ijekavianlatin]=Skeniranje uređaja -Description[sr@latin]=Skeniranje uređaja -Description[sv]=Sök igenom enhet -Description[uk]=Сканувати пристрій -Description[x-test]=xxScan devicexx -Description[zh_TW]=掃描裝置 -Policy=yes -Persistence=session - -[org.kde.kpmcore.scan.readsectorsused] -Name=Read used sectors action -Name[ca]=Acció de lectura dels sectors usats -Name[ca@valencia]=Acció de lectura dels sectors usats -Name[en_GB]=Read used sectors action -Name[es]=Acción de leer sectores usados -Name[lt]=Naudojamų sektorių nuskaitymo veiksmas -Name[nl]=Actie Gebruikte sectors lezen -Name[pl]=Działanie odczytu używanych sektorów -Name[pt]=Acção de leitura dos sectores usados -Name[sl]=Dejanje branja uporabljenih sektorjev -Name[sr]=Радња читања искоришћених сектора -Name[sr@ijekavian]=Радња читања искоришћених сектора -Name[sr@ijekavianlatin]=Radnja čitanja iskorišćenih sektora -Name[sr@latin]=Radnja čitanja iskorišćenih sektora -Name[sv]=Alternativ för att läsa använda sektorer -Name[uk]=Дія з читання даних щодо використаних секторів -Name[x-test]=xxRead used sectors actionxx -Name[zh_TW]=讀取已使用的磁柱動作 -Description=Read used sectors -Description[ca]=Lectura dels sectors usats -Description[ca@valencia]=Lectura dels sectors usats -Description[en_GB]=Read used sectors -Description[es]=Leer sectores usados -Description[lt]=Skaityti naudojamus sektorius -Description[nl]=Gebruikte sectors lezen -Description[pl]=Odczytaj używane sektory -Description[pt]=Ler os sectores usados -Description[sl]=Preberi uporabljene sektorje -Description[sr]=Читање искоришћених сектора -Description[sr@ijekavian]=Читање искоришћених сектора -Description[sr@ijekavianlatin]=Čitanje iskorišćenih sektora -Description[sr@latin]=Čitanje iskorišćenih sektora -Description[sv]=Läs använda sektorer -Description[uk]=Читання даних щодо використаних секторів -Description[x-test]=xxRead used sectorsxx -Description[zh_TW]=讀取已使用的磁柱 -Policy=yes -Persistence=session diff --git a/src/plugins/libparted/helpers/scan.cpp b/src/plugins/libparted/helpers/scan.cpp deleted file mode 100644 index de9b734..0000000 --- a/src/plugins/libparted/helpers/scan.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/************************************************************************* - * 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 "scan.h" -#include "core/partitiontable.h" -#include "plugins/libparted/pedflags.h" - -ActionReply Scan::scandevice(const QVariantMap& args) -{ - ActionReply reply; - - PedDevice* pedDevice = ped_device_get(args[QStringLiteral("deviceNode")].toString().toLocal8Bit().constData()); - - if (!pedDevice) { - reply.addData(QStringLiteral("pedDeviceError"), true); - return reply; - } - - reply.addData(QStringLiteral("model"), QString::fromUtf8(pedDevice->model)); - reply.addData(QStringLiteral("path"), QString::fromUtf8(pedDevice->path)); - reply.addData(QStringLiteral("heads"), pedDevice->bios_geom.heads); - reply.addData(QStringLiteral("sectors"), pedDevice->bios_geom.sectors); - reply.addData(QStringLiteral("cylinders"), pedDevice->bios_geom.cylinders); - reply.addData(QStringLiteral("sectorSize"), pedDevice->sector_size); - - PedDisk* pedDisk = ped_disk_new(pedDevice); - - if (!pedDisk) { - reply.addData(QStringLiteral("pedDiskError"), true); - return reply; - } - - quint64 firstUsableSector = pedDisk->dev->bios_geom.sectors; - - if (strcmp(pedDisk->type->name, "gpt") == 0) { - GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); - PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); - - if (geom) - firstUsableSector = geom->start; - else - firstUsableSector += 32; - } - - quint64 lastUsableSector = 0; - lastUsableSector = static_cast< quint64 >( pedDisk->dev->bios_geom.sectors ) * - pedDisk->dev->bios_geom.heads * - pedDisk->dev->bios_geom.cylinders - 1; - - bool isGPT = strcmp(pedDisk->type->name, "gpt") == 0; - if (isGPT) { - GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); - PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); - - if (geom) - lastUsableSector = geom->end; - else - lastUsableSector -= 32; - } - - reply.addData(QStringLiteral("pedDeviceError"), false); - reply.addData(QStringLiteral("pedDiskError"), false); - - reply.addData(QStringLiteral("typeName"), QString::fromUtf8(pedDisk->type->name)); - reply.addData(QStringLiteral("maxPrimaryPartitionCount"), ped_disk_get_max_primary_partition_count(pedDisk)); - reply.addData(QStringLiteral("firstUsableSector"), firstUsableSector); - reply.addData(QStringLiteral("lastUsableSector"), lastUsableSector); - - PedPartition* pedPartition = nullptr; - QList partitionPath; - QList partitionType; - QList partitionStart; - QList partitionEnd; - QList partitionBusy; - QList partitionLabel; - QList availableFlags; - QList activeFlags; - - while ((pedPartition = ped_disk_next_partition(pedDisk, pedPartition))) { - if (pedPartition->num < 1) - continue; - - partitionPath.append(QString::fromLatin1(ped_partition_get_path(pedPartition))); - partitionType.append(pedPartition->type); - partitionStart.append(pedPartition->geom.start); - partitionEnd.append(pedPartition->geom.end); - partitionBusy.append(ped_partition_is_busy(pedPartition)); - if (isGPT) - partitionLabel.append(QLatin1String(ped_partition_get_name(pedPartition))); - else - partitionLabel.append(QLatin1String()); - - // -------------------------------------------------------------------------- - // Get list of available flags - - PartitionTable::Flags flags; - - // We might get here with a pedPartition just picked up from libparted that is - // unallocated. Libparted doesn't like it if we ask for flags for unallocated - // space. - if (pedPartition->num > 0) - for (const auto &flag : flagmap) - if (ped_partition_is_flag_available(pedPartition, flag.pedFlag)) - // Workaround: libparted claims the hidden flag is available for extended partitions, but - // throws an error when we try to set or clear it. So skip this combination. Also see setFlag. - if (pedPartition->type != PED_PARTITION_EXTENDED || flag.flag != PartitionTable::FlagHidden) - flags |= flag.flag; - - availableFlags.append(static_cast(flags)); - // -------------------------------------------------------------------------- - // Get list of active flags - - flags = PartitionTable::FlagNone; - if (pedPartition->num > 0) - for (const auto &flag : flagmap) - if (ped_partition_is_flag_available(pedPartition, flag.pedFlag) && ped_partition_get_flag(pedPartition, flag.pedFlag)) - flags |= flag.flag; - - activeFlags.append(static_cast(flags)); - // -------------------------------------------------------------------------- - } - - reply.addData(QStringLiteral("availableFlags"), availableFlags); - reply.addData(QStringLiteral("activeFlags"), activeFlags); - reply.addData(QStringLiteral("partitionPath"), partitionPath); - reply.addData(QStringLiteral("partitionType"), partitionType); - reply.addData(QStringLiteral("partitionStart"), partitionStart); - reply.addData(QStringLiteral("partitionEnd"), partitionEnd); - reply.addData(QStringLiteral("partitionBusy"), partitionBusy); - reply.addData(QStringLiteral("partitionLabel"), partitionLabel); - - return reply; -} - -ActionReply Scan::readsectorsused(const QVariantMap& args) -{ - qint64 rval = -1; - - if (PedDevice* pedDevice = ped_device_get(args[QStringLiteral("deviceNode")].toString().toLocal8Bit().constData())) - if (PedDisk* pedDisk = ped_disk_new(pedDevice)) - if (PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk, args[QStringLiteral("firstSector")].toLongLong())) - if (PedFileSystem* pedFileSystem = ped_file_system_open(&pedPartition->geom)) - if (PedConstraint* pedConstraint = ped_file_system_get_resize_constraint(pedFileSystem)) - rval = pedConstraint->min_size; - - ActionReply reply; - reply.addData(QStringLiteral("sectorsUsed"), rval); - return reply; -} - -KAUTH_HELPER_MAIN("org.kde.kpmcore.scan", Scan) diff --git a/src/plugins/libparted/helpers/scan.h b/src/plugins/libparted/helpers/scan.h deleted file mode 100644 index dca38da..0000000 --- a/src/plugins/libparted/helpers/scan.h +++ /dev/null @@ -1,65 +0,0 @@ -/************************************************************************* - * 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 .* - *************************************************************************/ - -#if !defined(SCAN__H) - -#define SCAN__H - -#include -#include - -using namespace KAuth; - -class Scan : public QObject -{ - Q_OBJECT - -public Q_SLOTS: - ActionReply scandevice(const QVariantMap& args); - ActionReply readsectorsused(const QVariantMap& args); -}; - -// -------------------------------------------------------------------------- - -// The following structs and the typedef come from libparted's internal gpt sources. -// It's very unfortunate there is no public API to get at the first and last usable -// sector for GPT a partition table, so this is the only (libparted) way to get that -// information (another way would be to read the GPT header and parse the -// information ourselves; if the libparted devs begin changing these internal -// structs for each point release and break our code, we'll have to do just that). - -typedef struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node[6]; -} /* __attribute__ ((packed)) */ efi_guid_t; - - -struct __attribute__((packed)) _GPTDiskData { - PedGeometry data_area; - int entry_count; - efi_guid_t uuid; -}; - -typedef struct _GPTDiskData GPTDiskData; - -// -------------------------------------------------------------------------- - -#endif diff --git a/src/plugins/libparted/libpartedbackend.cpp b/src/plugins/libparted/libpartedbackend.cpp index 2243238..a918d5a 100644 --- a/src/plugins/libparted/libpartedbackend.cpp +++ b/src/plugins/libparted/libpartedbackend.cpp @@ -48,11 +48,11 @@ #include #include -#include #include #include #include +#include #include K_PLUGIN_FACTORY_WITH_JSON(LibPartedBackendFactory, "pmlibpartedbackendplugin.json", registerPlugin();) @@ -69,49 +69,182 @@ static PedExceptionOption pedExceptionHandler(PedException* e) return PED_EXCEPTION_UNHANDLED; } +// -------------------------------------------------------------------------- + +// The following structs and the typedef come from libparted's internal gpt sources. +// It's very unfortunate there is no public API to get at the first and last usable +// sector for GPT a partition table, so this is the only (libparted) way to get that +// information (another way would be to read the GPT header and parse the +// information ourselves; if the libparted devs begin changing these internal +// structs for each point release and break our code, we'll have to do just that). + +typedef struct { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; +} /* __attribute__ ((packed)) */ efi_guid_t; + + +struct __attribute__((packed)) _GPTDiskData { + PedGeometry data_area; + int entry_count; + efi_guid_t uuid; +}; + +typedef struct _GPTDiskData GPTDiskData; + +// -------------------------------------------------------------------------- + +/** Get the first sector a Partition may cover on a given Device + @param d the Device in question + @return the first sector usable by a Partition +*/ +static quint64 firstUsableSector(const Device& d) +{ + PedDevice* pedDevice = ped_device_get(d.deviceNode().toLatin1().constData()); + PedDisk* pedDisk = pedDevice ? ped_disk_new(pedDevice) : nullptr; + + quint64 rval = 0; + if (pedDisk) + rval = pedDisk->dev->bios_geom.sectors; + + if (pedDisk && strcmp(pedDisk->type->name, "gpt") == 0) { + GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); + PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); + + if (geom) + rval = geom->start; + else + rval += 32; + } + + ped_disk_destroy(pedDisk); + + return rval; +} + +/** Get the last sector a Partition may cover on a given Device + @param d the Device in question + @return the last sector usable by a Partition +*/ +static quint64 lastUsableSector(const Device& d) +{ + PedDevice* pedDevice = ped_device_get(d.deviceNode().toLatin1().constData()); + PedDisk* pedDisk = pedDevice ? ped_disk_new(pedDevice) : nullptr; + + quint64 rval = 0; + if (pedDisk) + rval = static_cast< quint64 >( pedDisk->dev->bios_geom.sectors ) * + pedDisk->dev->bios_geom.heads * + pedDisk->dev->bios_geom.cylinders - 1; + + if (pedDisk && strcmp(pedDisk->type->name, "gpt") == 0) { + GPTDiskData* gpt_disk_data = reinterpret_cast(pedDisk->disk_specific); + PedGeometry* geom = reinterpret_cast(&gpt_disk_data->data_area); + + if (geom) + rval = geom->end; + else + rval -= 32; + } + + ped_disk_destroy(pedDisk); + + return rval; +} + /** Reads sectors used on a FileSystem using libparted functions. @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 */ #if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT -static qint64 readSectorsUsedLibParted(const Partition& p) +static qint64 readSectorsUsedLibParted(PedDisk* pedDisk, const Partition& p) { - KAuth::Action action(QStringLiteral("org.kde.kpmcore.scan.readsectorsused")); - action.setHelperId(QStringLiteral("org.kde.kpmcore.scan")); - QVariantMap args = { - { QStringLiteral("deviceNode"), p.deviceNode() }, - { QStringLiteral("firstSector"), p.firstSector() } - }; - action.setArguments(args); - KAuth::ExecuteJob *job = action.execute(); - if (!job->exec()) { - qWarning() << "KAuth returned an error code: " << job->errorString(); - return -1; + Q_ASSERT(pedDisk); + + qint64 rval = -1; + + PedPartition* pedPartition = ped_disk_get_partition_by_sector(pedDisk, p.firstSector()); + + if (pedPartition) { + PedFileSystem* pedFileSystem = ped_file_system_open(&pedPartition->geom); + + if (pedFileSystem) { + if (PedConstraint* pedConstraint = ped_file_system_get_resize_constraint(pedFileSystem)) { + rval = pedConstraint->min_size; + ped_constraint_destroy(pedConstraint); + } + + ped_file_system_close(pedFileSystem); + } } - return job->data()[QLatin1String("sectorsUsed")].toLongLong(); + return rval; } #endif /** Reads the sectors used in a FileSystem and stores the result in the Partition's FileSystem object. + @param pedDisk pointer to pedDisk where the Partition and its FileSystem are @param p the Partition the FileSystem is on @param mountPoint mount point of the partition in question */ -static void readSectorsUsed(const DiskDevice& d, Partition& p, const QString& mountPoint) +static void readSectorsUsed(PedDisk* pedDisk, const Device& d, Partition& p, const QString& mountPoint) { const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint); if (p.isMounted() && freeSpaceInfo.isValid() && mountPoint != QString()) - p.fileSystem().setSectorsUsed(freeSpaceInfo.used() / d.logicalSectorSize()); + p.fileSystem().setSectorsUsed(freeSpaceInfo.used() / d.logicalSize()); else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportFileSystem) - p.fileSystem().setSectorsUsed(p.fileSystem().readUsedCapacity(p.deviceNode()) / d.logicalSectorSize()); + p.fileSystem().setSectorsUsed(p.fileSystem().readUsedCapacity(p.deviceNode()) / d.logicalSize()); #if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT - else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportBackend) - p.fileSystem().setSectorsUsed(readSectorsUsedLibParted(p)); + else if (p.fileSystem().supportGetUsed() == FileSystem::cmdSupportCore) + p.fileSystem().setSectorsUsed(readSectorsUsedLibParted(pedDisk, p)); +#else + Q_UNUSED(pedDisk); #endif } +static PartitionTable::Flags activeFlags(PedPartition* p) +{ + PartitionTable::Flags flags = PartitionTable::FlagNone; + + // We might get here with a pedPartition just picked up from libparted that is + // unallocated. Libparted doesn't like it if we ask for flags for unallocated + // space. + if (p->num <= 0) + return flags; + + for (const auto &flag : flagmap) + if (ped_partition_is_flag_available(p, flag.pedFlag) && ped_partition_get_flag(p, flag.pedFlag)) + flags |= flag.flag; + + return flags; +} + +static PartitionTable::Flags availableFlags(PedPartition* p) +{ + PartitionTable::Flags flags; + + // see above. + if (p->num <= 0) + return flags; + + for (const auto &flag : flagmap) { + if (ped_partition_is_flag_available(p, flag.pedFlag)) { + // Workaround: libparted claims the hidden flag is available for extended partitions, but + // throws an error when we try to set or clear it. So skip this combination. Also see setFlag. + if (p->type != PED_PARTITION_EXTENDED || flag.flag != PartitionTable::FlagHidden) + flags |= flag.flag; + } + } + + return flags; +} + /** Constructs a LibParted object. */ LibPartedBackend::LibPartedBackend(QObject*, const QList&) : CoreBackend() @@ -142,74 +275,37 @@ void LibPartedBackend::initFSSupport() #endif } -/** 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. +/** 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. + + @param d Device + @param pedDisk libparted pointer to the partition table */ -Device* LibPartedBackend::scanDevice(const QString& deviceNode) +void LibPartedBackend::scanDevicePartitions(Device& d, PedDisk* pedDisk) { - KAuth::Action scanAction(QStringLiteral("org.kde.kpmcore.scan.scandevice")); - scanAction.setHelperId(QStringLiteral("org.kde.kpmcore.scan")); - QVariantMap args = {{ QStringLiteral("deviceNode"), deviceNode }}; - scanAction.setArguments(args); - KAuth::ExecuteJob *job = scanAction.execute(); - if (!job->exec()) { - qWarning() << "KAuth returned an error code: " << job->errorString(); - return nullptr; - } + Q_ASSERT(pedDisk); + Q_ASSERT(d.partitionTable()); - bool pedDeviceError = job->data()[QLatin1String("pedDeviceError")].toBool(); + PedPartition* pedPartition = nullptr; - if (pedDeviceError) { - Log(Log::warning) << xi18nc("@info:status", "Could not access device %1", 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(); - - Log(Log::information) << xi18nc("@info:status", "Device found: %1", model); - - DiskDevice* d = new DiskDevice(model, path, heads, sectors, cylinders, sectorSize); - - 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 tableType = PartitionTable::nameToTableType(typeName); - CoreBackend::setPartitionTableForDevice(*d, new PartitionTable(tableType, firstUsableSector, lastUsableSector)); - CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), maxPrimaryPartitionCount); - - QList partitionPath = job->data()[QLatin1String("partitionPath")].toList(); - QList partitionType = job->data()[QLatin1String("partitionType")].toList(); - QList partitionStart = job->data()[QLatin1String("partitionStart")].toList(); - QList partitionEnd = job->data()[QLatin1String("partitionEnd")].toList(); - QList partitionBusy = job->data()[QLatin1String("partitionBusy")].toList(); - QList partitionLabel; - partitionLabel = job->data()[QLatin1String("partitionLabel")].toList(); - - quint32 totalPartitions = partitionPath.size(); QList 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(); + + while ((pedPartition = ped_disk_next_partition(pedDisk, pedPartition))) { + if (pedPartition->num < 1) + continue; PartitionRole::Roles r = PartitionRole::None; - FileSystem::Type fsType = detectFileSystem(partitionNode); + FileSystem::Type type = FileSystem::Unknown; + char* pedPath = ped_partition_get_path(pedPartition); + const QString partitionNode = pedPath ? QString::fromUtf8(pedPath) : QString(); + free(pedPath); + type = detectFileSystem(partitionNode); - switch (type) { + switch (pedPartition->type) { case PED_PARTITION_NORMAL: r = PartitionRole::Primary; break; @@ -228,13 +324,13 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) } // Find an extended partition this partition is in. - PartitionNode* parent = d->partitionTable()->findPartitionBySector(start, PartitionRole(PartitionRole::Extended)); + PartitionNode* parent = d.partitionTable()->findPartitionBySector(pedPartition->geom.start, PartitionRole(PartitionRole::Extended)); // None found, so it's a primary in the device's partition table. if (parent == nullptr) - parent = d->partitionTable(); + parent = d.partitionTable(); - FileSystem* fs = FileSystemFactory::create(fsType, start, end); + FileSystem* fs = FileSystemFactory::create(type, pedPartition->geom.start, pedPartition->geom.end); fs->scan(partitionNode); QString mountPoint; bool mounted; @@ -251,21 +347,17 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) mounted = FileSystem::detectMountStatus(fs, partitionNode); } - QList availableFlags = job->data()[QLatin1String("availableFlags")].toList(); - PartitionTable::Flags available = static_cast(availableFlags[i].toInt()); - QList activeFlags = job->data()[QLatin1String("activeFlags")].toList(); - PartitionTable::Flags active = static_cast(activeFlags[i].toInt()); - Partition* part = new Partition(parent, *d, PartitionRole(r), fs, start, end, partitionNode, available, mountPoint, mounted, active); + Partition* part = new Partition(parent, d, PartitionRole(r), fs, pedPartition->geom.start, pedPartition->geom.end, partitionNode, availableFlags(pedPartition), mountPoint, mounted, activeFlags(pedPartition)); if (!part->roles().has(PartitionRole::Luks)) - readSectorsUsed(*d, *part, mountPoint); + readSectorsUsed(pedDisk, d, *part, mountPoint); if (fs->supportGetLabel() != FileSystem::cmdSupportNone) fs->setLabel(fs->readLabel(part->deviceNode())); // GPT partitions support partition labels and partition UUIDs - if(tableType == PartitionTable::TableType::gpt) - part->setLabel(partitionLabel[i].toString()); + if(d.partitionTable()->type() == PartitionTable::TableType::gpt) + fs->setLabel(fs->readLabel(part->deviceNode())); if (fs->supportGetUUID() != FileSystem::cmdSupportNone) fs->setUUID(fs->readUUID(part->deviceNode())); @@ -274,14 +366,43 @@ Device* LibPartedBackend::scanDevice(const QString& deviceNode) partitions.append(part); } - d->partitionTable()->updateUnallocated(*d); + d.partitionTable()->updateUnallocated(d); - if (d->partitionTable()->isSectorBased(*d)) - d->partitionTable()->setType(*d, PartitionTable::msdos_sectorbased); + if (d.partitionTable()->isSectorBased(d)) + d.partitionTable()->setType(d, PartitionTable::msdos_sectorbased); foreach(const Partition * part, partitions) - PartitionAlignment::isAligned(*d, *part); + PartitionAlignment::isAligned(d, *part); +} +/** 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* LibPartedBackend::scanDevice(const QString& deviceNode) +{ + PedDevice* pedDevice = ped_device_get(deviceNode.toLocal8Bit().constData()); + + if (pedDevice == nullptr) { + Log(Log::warning) << xi18nc("@info:status", "Could not access device %1", deviceNode); + return nullptr; + } + + Log(Log::information) << xi18nc("@info:status", "Device found: %1", QString::fromUtf8(pedDevice->model)); + + DiskDevice* d = new DiskDevice(QString::fromUtf8(pedDevice->model), QString::fromUtf8(pedDevice->path), pedDevice->bios_geom.heads, pedDevice->bios_geom.sectors, pedDevice->bios_geom.cylinders, pedDevice->sector_size); + + PedDisk* pedDisk = ped_disk_new(pedDevice); + + if (pedDisk) { + const PartitionTable::TableType type = PartitionTable::nameToTableType(QString::fromUtf8(pedDisk->type->name)); + CoreBackend::setPartitionTableForDevice(*d, new PartitionTable(type, firstUsableSector(*d), lastUsableSector(*d))); + CoreBackend::setPartitionTableMaxPrimaries(*d->partitionTable(), ped_disk_get_max_primary_partition_count(pedDisk)); + + scanDevicePartitions(*d, pedDisk); + } + + ped_device_destroy(pedDevice); return d; } diff --git a/src/plugins/libparted/libpartedbackend.h b/src/plugins/libparted/libpartedbackend.h index 45d0b54..7337d9b 100644 --- a/src/plugins/libparted/libpartedbackend.h +++ b/src/plugins/libparted/libpartedbackend.h @@ -71,6 +71,7 @@ public: private: static PedPartitionFlag getPedFlag(PartitionTable::Flag flag); + void scanDevicePartitions(Device& d, PedDisk* pedDisk); }; #endif