diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index c86cf015c..08278a3b6 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -169,39 +169,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO lastSectorForRoot -= suggestedSwapSizeB / dev->logicalSize() + 1; } - Partition* rootPartition = nullptr; - if ( o.luksPassphrase.isEmpty() ) - { - rootPartition = KPMHelpers::createNewPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::typeForName( defaultFsType ), - firstFreeSector, - lastSectorForRoot, - PartitionTable::FlagNone - ); - } - else - { - rootPartition = KPMHelpers::createNewEncryptedPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::typeForName( defaultFsType ), - firstFreeSector, - lastSectorForRoot, - o.luksPassphrase, - PartitionTable::FlagNone - ); - } - PartitionInfo::setFormat( rootPartition, true ); - PartitionInfo::setMountPoint( rootPartition, "/" ); - // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. - // Otherwise they ignore the device in boot-order, so add it here. - core->createPartition( dev, rootPartition, - rootPartition->activeFlags() | ( isEfi ? PartitionTable::FlagNone : PartitionTable::FlagBoot ) - ); + core->layoutApply( dev, firstFreeSector, lastSectorForRoot, o.luksPassphrase ); if ( shouldCreateSwap ) { @@ -245,6 +213,8 @@ doReplacePartition( PartitionCoreModule* core, Partition* partition, Choices::ReplacePartitionOptions o ) { + qint64 firstSector, lastSector; + cDebug() << "doReplacePartition for device" << partition->partitionPath(); QString defaultFsType = o.defaultFsType; @@ -267,38 +237,13 @@ doReplacePartition( PartitionCoreModule* core, } } - Partition* newPartition = nullptr; - if ( o.luksPassphrase.isEmpty() ) - { - newPartition = KPMHelpers::createNewPartition( - partition->parent(), - *dev, - newRoles, - FileSystem::typeForName( defaultFsType ), - partition->firstSector(), - partition->lastSector(), - PartitionTable::FlagNone - ); - } - else - { - newPartition = KPMHelpers::createNewEncryptedPartition( - partition->parent(), - *dev, - newRoles, - FileSystem::typeForName( defaultFsType ), - partition->firstSector(), - partition->lastSector(), - o.luksPassphrase, - PartitionTable::FlagNone - ); - } - PartitionInfo::setMountPoint( newPartition, "/" ); - PartitionInfo::setFormat( newPartition, true ); - + // Save the first and last sector values as the partition will be deleted + firstSector = partition->firstSector(); + lastSector = partition->lastSector(); if ( !partition->roles().has( PartitionRole::Unallocated ) ) core->deletePartition( dev, partition ); - core->createPartition( dev, newPartition ); + + core->layoutApply( dev, firstSector, lastSector, o.luksPassphrase ); core->dumpQueue(); } diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 8abcf7035..9af5665a5 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -787,6 +787,30 @@ PartitionCoreModule::initLayout( const QVariantList& config ) } } +void +PartitionCoreModule::layoutApply( Device *dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase ) +{ + bool isEfi = PartUtils::isEfiSystem(); + QList< Partition* > partList = m_partLayout->execute( dev, firstSector, lastSector, luksPassphrase ); + + foreach ( Partition *part, partList ) + { + if ( part->mountPoint() == "/" ) + { + createPartition( dev, part, + part->activeFlags() | ( isEfi ? PartitionTable::FlagNone : PartitionTable::FlagBoot ) + ); + } + else + { + createPartition( dev, part ); + } + } +} + void PartitionCoreModule::revert() { diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 55961ce58..2b2c73a3f 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -159,6 +159,7 @@ public: void initLayout(); void initLayout( const QVariantList& config ); + void layoutApply( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); /** * @brief jobs creates and returns a list of jobs which can then apply the changes * requested by the user. diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 02ec29526..d0c1a7c94 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -18,6 +18,12 @@ #include "core/PartitionLayout.h" +#include "core/KPMHelpers.h" +#include "core/PartitionActions.h" +#include "core/PartitionInfo.h" + +#include +#include #include PartitionLayout::PartitionLayout() @@ -113,3 +119,96 @@ PartitionLayout::addEntry( QString label, QString mountPoint, QString fs, QStrin partLayout.append( entry ); } + +static qint64 +sizeToSectors( double size, PartitionLayout::SizeUnit unit, qint64 totalSize, qint64 logicalSize ) +{ + qint64 sectors; + double tmp; + + if ( unit == PartitionLayout::SizeUnit::Percent ) + { + tmp = static_cast( totalSize ) * size / 100; + sectors = static_cast( tmp ); + } + else + { + tmp = size; + if ( unit >= PartitionLayout::SizeUnit::KiB ) + tmp *= 1024; + if ( unit >= PartitionLayout::SizeUnit::MiB ) + tmp *= 1024; + if ( unit >= PartitionLayout::SizeUnit::GiB ) + tmp *= 1024; + + sectors = PartitionActions::bytesToSectors( static_cast( tmp ), + logicalSize + ); + } + + return sectors; +} + +QList< Partition* > +PartitionLayout::execute( Device *dev, qint64 firstSector, + qint64 lastSector, QString luksPassphrase ) +{ + QList< Partition* > partList; + qint64 size, minSize, end; + qint64 totalSize = lastSector - firstSector; + qint64 availableSize = totalSize; + + // TODO: Refine partition sizes to make sure there is room for every partition + // Use a default (200-500M ?) minimum size for partition without minSize + + foreach( const PartitionLayout::PartitionEntry& part, partLayout ) + { + Partition *currentPartition = nullptr; + + // Calculate partition size + size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); + minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); + if ( size < minSize ) + size = minSize; + if ( size > availableSize ) + size = availableSize; + end = firstSector + size; + + if ( luksPassphrase.isEmpty() ) + { + currentPartition = KPMHelpers::createNewPartition( + dev->partitionTable(), + *dev, + PartitionRole( PartitionRole::Primary ), + static_cast(part.partFileSystem), + firstSector, + end, + PartitionTable::FlagNone + ); + } + else + { + currentPartition = KPMHelpers::createNewEncryptedPartition( + dev->partitionTable(), + *dev, + PartitionRole( PartitionRole::Primary ), + static_cast(part.partFileSystem), + firstSector, + end, + luksPassphrase, + PartitionTable::FlagNone + ); + } + PartitionInfo::setFormat( currentPartition, true ); + PartitionInfo::setMountPoint( currentPartition, part.partMountPoint ); + if ( !part.partLabel.isEmpty() ) + currentPartition->fileSystem().setLabel( part.partLabel ); + // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. + // Otherwise they ignore the device in boot-order, so add it here. + partList.append( currentPartition ); + firstSector = end + 1; + availableSize -= size; + } + + return partList; +} diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index eadb8b012..e3eb7296b 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -63,6 +63,12 @@ public: void addEntry( QString mountPoint, QString size, QString min = "" ); void addEntry( QString label, QString mountPoint, QString fs, QString size, QString min = "" ); + /** + * @brief Apply the current partition layout to the selected drive space. + * @return A list of Partition objects. + */ + QList< Partition* > execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); + private: QList< PartitionEntry > partLayout; };