Commit 0d284759 authored by Arnaud Ferraris's avatar Arnaud Ferraris

[partition] Apply custom partition layout for Erase and Replace choices

This patches add new methods to both PartitionLayout and
PartitionCoreModule classes which apply the partition layout to the
available drive space.

In addition, the partition creation code from PartitioinActions is
removed to call the newly created methods instead, thus applying the
custom partition layout when the "Erase whole disk" and "Replace
partition" choices are selected.
Signed-off-by: default avatarArnaud Ferraris <arnaud.ferraris@collabora.com>
parent f863912a
......@@ -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();
}
......
......@@ -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()
{
......
......@@ -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.
......
......@@ -18,6 +18,12 @@
#include "core/PartitionLayout.h"
#include "core/KPMHelpers.h"
#include "core/PartitionActions.h"
#include "core/PartitionInfo.h"
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystem.h>
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<double>( totalSize ) * size / 100;
sectors = static_cast<qint64>( 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<unsigned long long>( 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<FileSystem::Type>(part.partFileSystem),
firstSector,
end,
PartitionTable::FlagNone
);
}
else
{
currentPartition = KPMHelpers::createNewEncryptedPartition(
dev->partitionTable(),
*dev,
PartitionRole( PartitionRole::Primary ),
static_cast<FileSystem::Type>(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;
}
......@@ -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;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment