diff --git a/README.md b/README.md index 7ad26e2c5..a2cb426b7 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,10 @@ [![Coverity Scan Build Status](https://scan.coverity.com/projects/5389/badge.svg)](https://scan.coverity.com/projects/5389) [![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSE) -| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](CONTRIBUTING.md) | [Freenode (IRC): #calamares](https://webchat.freenode.net/?channel=#calamares?nick=guest|) | [Wiki](https://github.com/calamares/calamares/wiki) | -|:-----------------------------------------:|:----------------------:|:-----------------------:|:--------------------------:|:--------------------------:| + +| [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](CONTRIBUTING.md) | [Freenode (IRC): #calamares](https://webchat.freenode.net/?channel=#calamares?nick=guest) | [Wiki](https://github.com/calamares/calamares/wiki) | +|:--:|:--:|:--:|:--:|:--:| + > Calamares is a distribution-independent system installer, with an advanced partitioning > feature for both manual and automated partitioning operations. Calamares is designed to diff --git a/src/libcalamares/partition/KPMHelper.h b/src/libcalamares/partition/KPMHelper.h new file mode 100644 index 000000000..f6007b119 --- /dev/null +++ b/src/libcalamares/partition/KPMHelper.h @@ -0,0 +1,43 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +/* + * KPMCore header file inclusion. + * + * Includes the system KPMCore headers without warnings (by switching off + * the expected warnings). + */ +#ifndef PARTITION_KPMHELPER_H +#define PARTITION_KPMHELPER_H + +// The kpmcore headers are not C++17 warning-proof, especially +// with picky compilers like Clang 10. Since we use Clang for the +// find-all-the-warnings case, switch those warnings off for +// the we-can't-change-them system headers. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" +#pragma clang diagnostic ignored "-Wsuggest-destructor-override" +#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif diff --git a/src/libcalamares/partition/PartitionQuery.cpp b/src/libcalamares/partition/PartitionQuery.cpp index beba6b9bc..4c9c1549d 100644 --- a/src/libcalamares/partition/PartitionQuery.cpp +++ b/src/libcalamares/partition/PartitionQuery.cpp @@ -27,14 +27,14 @@ using ::Device; using ::Partition; bool -isPartitionFreeSpace( Partition* partition ) +isPartitionFreeSpace( const Partition* partition ) { return partition->roles().has( PartitionRole::Unallocated ); } bool -isPartitionNew( Partition* partition ) +isPartitionNew( const Partition* partition ) { #if defined( WITH_KPMCORE4API ) constexpr auto NewState = Partition::State::New; @@ -67,11 +67,15 @@ findPartitionByPath( const QList< Device* >& devices, const QString& path ) } for ( auto device : devices ) + { for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) + { if ( ( *it )->partitionPath() == path.simplified() ) { return *it; } + } + } return nullptr; } @@ -81,11 +85,15 @@ findPartitions( const QList< Device* >& devices, std::function< bool( Partition* { QList< Partition* > results; for ( auto device : devices ) + { for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) + { if ( criterionFunction( *it ) ) { results.append( *it ); } + } + } return results; } diff --git a/src/libcalamares/partition/PartitionQuery.h b/src/libcalamares/partition/PartitionQuery.h index 817966d35..9ef5f41f6 100644 --- a/src/libcalamares/partition/PartitionQuery.h +++ b/src/libcalamares/partition/PartitionQuery.h @@ -34,14 +34,14 @@ using ::Device; using ::Partition; /** @brief Is this a free-space area? */ -bool isPartitionFreeSpace( Partition* ); +bool isPartitionFreeSpace( const Partition* ); /** @brief Is this partition newly-to-be-created? * * Returns true if the partition is planned to be created by the installer as * opposed to already existing on the disk. */ -bool isPartitionNew( Partition* ); +bool isPartitionNew( const Partition* ); /** * Iterates on all devices and return the first partition which is (already) diff --git a/src/modules/keyboard/Config.cpp b/src/modules/keyboard/Config.cpp index 6475d9bc8..5d5e80d5f 100644 --- a/src/modules/keyboard/Config.cpp +++ b/src/modules/keyboard/Config.cpp @@ -108,7 +108,7 @@ xkbmap_query_grp_option() //it's either in the end of line or before the other option so \s or , int lastIndex = outputLine.indexOf( QRegExp( "[\\s,]" ), index ); - return outputLine.mid( index, lastIndex - 1 ); + return outputLine.mid( index, lastIndex - index ); } AdditionalLayoutInfo diff --git a/src/modules/keyboard/non-ascii-layouts b/src/modules/keyboard/non-ascii-layouts index 83935c190..34035c91b 100644 --- a/src/modules/keyboard/non-ascii-layouts +++ b/src/modules/keyboard/non-ascii-layouts @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# # Layouts stored here need additional layout (usually us) to provide ASCII support for user #layout additional-layout additional-variant vconsole-keymap diff --git a/src/modules/locale/timezonewidget/TimeZoneImage.cpp b/src/modules/locale/timezonewidget/TimeZoneImage.cpp index 54aa1afd5..ad772ef63 100644 --- a/src/modules/locale/timezonewidget/TimeZoneImage.cpp +++ b/src/modules/locale/timezonewidget/TimeZoneImage.cpp @@ -24,9 +24,6 @@ static_assert( TimeZoneImageList::zoneCount == ( sizeof( zoneNames ) / sizeof( z #define ZONE_NAME QStringLiteral( "zone" ) -/* static constexpr */ const int TimeZoneImageList::zoneCount; -/* static constexpr */ const QSize TimeZoneImageList::imageSize; - static_assert( TimeZoneImageList::zoneCount == 37, "Incorrect number of zones" ); TimeZoneImageList::TimeZoneImageList() {} diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index a514b9c34..07ab5acc1 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * Copyright 2018-2019 Adriaan de Groot + * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot * SPDX-FileCopyrightText: 2019 Collabora Ltd * SPDX-License-Identifier: GPL-3.0-or-later * @@ -59,7 +59,7 @@ convenienceName( const Partition* const candidate ) QString p; QTextStream s( &p ); - s << static_cast(candidate); // No good name available, use pointer address + s << static_cast< const void* >( candidate ); // No good name available, use pointer address return p; } diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 3327eb50b..706f99017 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -860,82 +860,10 @@ PartitionCoreModule::setBootLoaderInstallPath( const QString& path ) m_bootLoaderInstallPath = path; } -void -PartitionCoreModule::initLayout() -{ - m_partLayout = new PartitionLayout(); - - m_partLayout->addEntry( QString( "/" ), QString( "100%" ) ); -} - void PartitionCoreModule::initLayout( const QVariantList& config ) { - bool ok; - QString sizeString; - QString minSizeString; - QString maxSizeString; - - m_partLayout = new PartitionLayout(); - - for ( const auto& r : config ) - { - QVariantMap pentry = r.toMap(); - - if ( !pentry.contains( "name" ) || !pentry.contains( "mountPoint" ) || !pentry.contains( "filesystem" ) - || !pentry.contains( "size" ) ) - { - cError() << "Partition layout entry #" << config.indexOf( r ) - << "lacks mandatory attributes, switching to default layout."; - delete ( m_partLayout ); - initLayout(); - break; - } - - if ( pentry.contains( "size" ) && CalamaresUtils::getString( pentry, "size" ).isEmpty() ) - { - sizeString.setNum( CalamaresUtils::getInteger( pentry, "size", 0 ) ); - } - else - { - sizeString = CalamaresUtils::getString( pentry, "size" ); - } - - if ( pentry.contains( "minSize" ) && CalamaresUtils::getString( pentry, "minSize" ).isEmpty() ) - { - minSizeString.setNum( CalamaresUtils::getInteger( pentry, "minSize", 0 ) ); - } - else - { - minSizeString = CalamaresUtils::getString( pentry, "minSize" ); - } - - if ( pentry.contains( "maxSize" ) && CalamaresUtils::getString( pentry, "maxSize" ).isEmpty() ) - { - maxSizeString.setNum( CalamaresUtils::getInteger( pentry, "maxSize", 0 ) ); - } - else - { - maxSizeString = CalamaresUtils::getString( pentry, "maxSize" ); - } - - if ( !m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ), - CalamaresUtils::getString( pentry, "uuid" ), - CalamaresUtils::getString( pentry, "type" ), - CalamaresUtils::getUnsignedInteger( pentry, "attributes", 0 ), - CalamaresUtils::getString( pentry, "mountPoint" ), - CalamaresUtils::getString( pentry, "filesystem" ), - CalamaresUtils::getSubMap( pentry, "features", ok ), - sizeString, - minSizeString, - maxSizeString ) ) - { - cError() << "Partition layout entry #" << config.indexOf( r ) << "is invalid, switching to default layout."; - delete ( m_partLayout ); - initLayout(); - break; - } - } + m_partLayout.init( config ); } void @@ -947,7 +875,7 @@ PartitionCoreModule::layoutApply( Device* dev, const PartitionRole& role ) { bool isEfi = PartUtils::isEfiSystem(); - QList< Partition* > partList = m_partLayout->execute( dev, firstSector, lastSector, luksPassphrase, parent, role ); + QList< Partition* > partList = m_partLayout.createPartitions( dev, firstSector, lastSector, luksPassphrase, parent, role ); // Partition::mountPoint() tells us where it is mounted **now**, while // PartitionInfo::mountPoint() says where it will be mounted in the target system. diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 1e4179b97..46feb5f94 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -156,8 +156,7 @@ public: /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); - void initLayout(); - void initLayout( const QVariantList& config ); + void initLayout( const QVariantList& config = QVariantList() ); void layoutApply( Device* dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); void layoutApply( Device* dev, @@ -256,7 +255,7 @@ private: bool m_hasRootMountPoint = false; bool m_isDirty = false; QString m_bootLoaderInstallPath; - PartitionLayout* m_partLayout; + PartitionLayout m_partLayout; OsproberEntryList m_osproberLines; diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index d42e7b568..15b18da93 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -21,6 +21,8 @@ #include "core/PartitionActions.h" #include "core/PartitionInfo.h" +#include "utils/Variant.h" + #include #include #include @@ -48,12 +50,6 @@ PartitionLayout::PartitionLayout() { } -PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry ) - : PartitionLayout() -{ - m_partLayout.append( entry ); -} - PartitionLayout::PartitionLayout( const PartitionLayout& layout ) : m_defaultFsType( layout.m_defaultFsType ) , m_partLayout( layout.m_partLayout ) @@ -62,270 +58,247 @@ PartitionLayout::PartitionLayout( const PartitionLayout& layout ) PartitionLayout::~PartitionLayout() {} -bool -PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) -{ - if ( !entry.isValid() ) - { - cError() << "Partition size is invalid or has min size > max size"; - return false; - } - - m_partLayout.append( entry ); - - return true; -} - PartitionLayout::PartitionEntry::PartitionEntry() : partAttributes( 0 ) { } -PartitionLayout::PartitionEntry::PartitionEntry( const QString& size, const QString& min, const QString& max ) +PartitionLayout::PartitionEntry::PartitionEntry( const QString& mountPoint, const QString& size, const QString& minSize, const QString& maxSize ) : partAttributes( 0 ) + , partMountPoint( mountPoint ) , partSize( size ) - , partMinSize( min ) - , partMaxSize( max ) + , partMinSize( minSize ) + , partMaxSize( maxSize ) { } -bool -PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const QString& min, const QString& max ) +PartitionLayout::PartitionEntry::PartitionEntry( const QString& label, + const QString& uuid, + const QString& type, + quint64 attributes, + const QString& mountPoint, + const QString& fs, + const QVariantMap& features, + const QString& size, + const QString& minSize, + const QString& maxSize ) + : partLabel( label ) + , partUUID( uuid ) + , partType( type ) + , partAttributes( attributes ) + , partMountPoint( mountPoint ) + , partFeatures( features ) + , partSize( size ) + , partMinSize( minSize ) + , partMaxSize( maxSize ) { - PartitionLayout::PartitionEntry entry( size, min, max ); + PartUtils::findFS( fs, &partFileSystem ); +} +PartitionLayout::PartitionEntry::PartitionEntry( const PartitionEntry& e ) + : partLabel( e.partLabel ) + , partUUID( e.partUUID ) + , partType( e.partType ) + , partAttributes( e.partAttributes ) + , partMountPoint( e.partMountPoint ) + , partFileSystem( e.partFileSystem ) + , partFeatures( e.partFeatures ) + , partSize( e.partSize ) + , partMinSize( e.partMinSize ) + , partMaxSize( e.partMaxSize ) +{ +} + + +bool +PartitionLayout::addEntry( const PartitionEntry& entry ) +{ if ( !entry.isValid() ) { - cError() << "Partition size" << size << "is invalid or" << min << ">" << max; return false; } - if ( mountPoint.isEmpty() || !mountPoint.startsWith( QString( "/" ) ) ) - { - cError() << "Partition mount point" << mountPoint << "is invalid"; - return false; - } - - entry.partMountPoint = mountPoint; - entry.partFileSystem = m_defaultFsType; m_partLayout.append( entry ); return true; } -bool -PartitionLayout::addEntry( const QString& label, - const QString& uuid, - const QString& type, - quint64 attributes, - const QString& mountPoint, - const QString& fs, - const QVariantMap& features, - const QString& size, - const QString& min, - const QString& max ) +void +PartitionLayout::init( const QVariantList& config ) { - PartitionLayout::PartitionEntry entry( size, min, max ); + bool ok; - if ( !entry.isValid() ) + m_partLayout.clear(); + + for ( const auto& r : config ) { - cError() << "Partition size" << size << "is invalid or" << min << ">" << max; - return false; - } - if ( mountPoint.isEmpty() || !mountPoint.startsWith( QString( "/" ) ) ) - { - cError() << "Partition mount point" << mountPoint << "is invalid"; - return false; + QVariantMap pentry = r.toMap(); + + if ( !pentry.contains( "name" ) || !pentry.contains( "mountPoint" ) || !pentry.contains( "filesystem" ) + || !pentry.contains( "size" ) ) + { + cError() << "Partition layout entry #" << config.indexOf( r ) + << "lacks mandatory attributes, switching to default layout."; + m_partLayout.clear(); + break; + } + + if ( !addEntry( { CalamaresUtils::getString( pentry, "name" ), + CalamaresUtils::getString( pentry, "uuid" ), + CalamaresUtils::getString( pentry, "type" ), + CalamaresUtils::getUnsignedInteger( pentry, "attributes", 0 ), + CalamaresUtils::getString( pentry, "mountPoint" ), + CalamaresUtils::getString( pentry, "filesystem" ), + CalamaresUtils::getSubMap( pentry, "features", ok ), + CalamaresUtils::getString( pentry, "size", QStringLiteral( "0" ) ), + CalamaresUtils::getString( pentry, "minSize", QStringLiteral( "0" ) ), + CalamaresUtils::getString( pentry, "maxSize", QStringLiteral( "0" ) ) } ) ) + { + cError() << "Partition layout entry #" << config.indexOf( r ) << "is invalid, switching to default layout."; + m_partLayout.clear(); + break; + } } - entry.partLabel = label; - entry.partUUID = uuid; - entry.partType = type; - entry.partAttributes = attributes; - entry.partMountPoint = mountPoint; - PartUtils::findFS( fs, &entry.partFileSystem ); - if ( entry.partFileSystem == FileSystem::Unknown ) + if ( !m_partLayout.count() ) { - entry.partFileSystem = m_defaultFsType; + addEntry( { QString( "/" ), QString( "100%" ) } ); } - entry.partFeatures = features; - - m_partLayout.append( entry ); - - return true; } QList< Partition* > -PartitionLayout::execute( Device* dev, - qint64 firstSector, - qint64 lastSector, - QString luksPassphrase, - PartitionNode* parent, - const PartitionRole& role ) +PartitionLayout::createPartitions( Device* dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ) { QList< Partition* > partList; // Map each partition entry to its requested size (0 when calculated later) - QMap< const PartitionLayout::PartitionEntry*, qint64 > partSizeMap; - qint64 totalSize = lastSector - firstSector + 1; - qint64 availableSize = totalSize; + QMap< const PartitionLayout::PartitionEntry*, qint64 > partSectorsMap; + const qint64 totalSectors = lastSector - firstSector + 1; + qint64 currentSector, availableSectors = totalSectors; - // Let's check if we have enough space for each partSize - for ( const auto& part : qAsConst( m_partLayout ) ) + // Let's check if we have enough space for each partitions, using the size + // propery or the min-size property if unit is in percentage. + for ( const auto& entry : qAsConst( m_partLayout ) ) { - if ( !part.partSize.isValid() ) + if ( !entry.partSize.isValid() ) { - cWarning() << "Partition" << part.partMountPoint << "size is invalid, skipping..."; + cWarning() << "Partition" << entry.partMountPoint << "size is invalid, skipping..."; continue; } // Calculate partition size: Rely on "possibly uninitialized use" // warnings to ensure that all the cases are covered below. - qint64 size; // We need to ignore the percent-defined until later - if ( part.partSize.unit() != CalamaresUtils::Partition::SizeUnit::Percent ) + qint64 sectors = 0; + if ( entry.partSize.unit() != CalamaresUtils::Partition::SizeUnit::Percent ) { - size = part.partSize.toSectors( totalSize, dev->logicalSize() ); + sectors = entry.partSize.toSectors( totalSectors, dev->logicalSize() ); } - else + else if ( entry.partMinSize.isValid() ) { - if ( part.partMinSize.isValid() ) - { - size = part.partMinSize.toSectors( totalSize, dev->logicalSize() ); - } - else - { - size = 0; - } + sectors = entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ); } - - partSizeMap.insert( &part, size ); - availableSize -= size; + partSectorsMap.insert( &entry, sectors ); + availableSectors -= sectors; } - // Use partMinSize and see if we can do better afterward. - if ( availableSize < 0 ) + // There is not enough space for all partitions, use the min-size property + // and see if we can do better afterward. + if ( availableSectors < 0 ) { - availableSize = totalSize; - for ( const auto& part : qAsConst( m_partLayout ) ) + availableSectors = totalSectors; + for ( const auto& entry : qAsConst( m_partLayout ) ) { - qint64 size; - - if ( part.partMinSize.isValid() ) + qint64 sectors = partSectorsMap.value( &entry ); + if ( entry.partMinSize.isValid() ) { - size = part.partMinSize.toSectors( totalSize, dev->logicalSize() ); + sectors = entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ); + partSectorsMap.insert( &entry, sectors ); } - else if ( part.partSize.isValid() ) - { - if ( part.partSize.unit() != CalamaresUtils::Partition::SizeUnit::Percent ) - { - size = part.partSize.toSectors( totalSize, dev->logicalSize() ); - } - else - { - size = 0; - } - } - else - { - size = 0; - } - - partSizeMap.insert( &part, size ); - availableSize -= size; + availableSectors -= sectors; } } - // Assign size for percentage-defined partitions - for ( const auto& part : qAsConst( m_partLayout ) ) + // Assign sectors for percentage-defined partitions. + for ( const auto& entry : qAsConst( m_partLayout ) ) { - if ( part.partSize.unit() == CalamaresUtils::Partition::SizeUnit::Percent ) + if ( entry.partSize.unit() == CalamaresUtils::Partition::SizeUnit::Percent ) { - qint64 size = partSizeMap.value( &part ); - size = part.partSize.toSectors( availableSize + size, dev->logicalSize() ); - if ( part.partMinSize.isValid() ) + qint64 sectors = entry.partSize.toSectors( availableSectors + partSectorsMap.value( &entry ), + dev->logicalSize() ); + if ( entry.partMinSize.isValid() ) { - qint64 minSize = part.partMinSize.toSectors( totalSize, dev->logicalSize() ); - if ( minSize > size ) - { - size = minSize; - } + sectors = std::max( sectors, entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ) ); } - if ( part.partMaxSize.isValid() ) + if ( entry.partMaxSize.isValid() ) { - qint64 maxSize = part.partMaxSize.toSectors( totalSize, dev->logicalSize() ); - if ( maxSize < size ) - { - size = maxSize; - } + sectors = std::min( sectors, entry.partMaxSize.toSectors( totalSectors, dev->logicalSize() ) ); } - - partSizeMap.insert( &part, size ); + partSectorsMap.insert( &entry, sectors ); } } - 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 - - for ( const auto& part : qAsConst( m_partLayout ) ) + // Create the partitions. + currentSector = firstSector; + availableSectors = totalSectors; + for ( const auto& entry : qAsConst( m_partLayout ) ) { - qint64 size, end; - Partition* currentPartition = nullptr; - - size = partSizeMap.value( &part ); - - // Adjust partition size based on available space - if ( size > availableSize ) + // Adjust partition size based on available space. + qint64 sectors = partSectorsMap.value( &entry ); + sectors = std::min( sectors, availableSectors ); + if ( sectors == 0 ) { - size = availableSize; + continue; } - end = firstSector + std::max( size - 1, Q_INT64_C( 0 ) ); - + Partition* part = nullptr; if ( luksPassphrase.isEmpty() ) { - currentPartition = KPMHelpers::createNewPartition( - parent, *dev, role, part.partFileSystem, firstSector, end, KPM_PARTITION_FLAG( None ) ); + part = KPMHelpers::createNewPartition( + parent, *dev, role, entry.partFileSystem, currentSector, currentSector + sectors - 1, KPM_PARTITION_FLAG( None ) ); } else { - currentPartition = KPMHelpers::createNewEncryptedPartition( - parent, *dev, role, part.partFileSystem, firstSector, end, luksPassphrase, KPM_PARTITION_FLAG( None ) ); + part = KPMHelpers::createNewEncryptedPartition( + parent, *dev, role, entry.partFileSystem, currentSector, currentSector + sectors - 1, luksPassphrase, KPM_PARTITION_FLAG( None ) ); } - PartitionInfo::setFormat( currentPartition, true ); - PartitionInfo::setMountPoint( currentPartition, part.partMountPoint ); - if ( !part.partLabel.isEmpty() ) + PartitionInfo::setFormat( part, true ); + PartitionInfo::setMountPoint( part, entry.partMountPoint ); + if ( !entry.partLabel.isEmpty() ) { - currentPartition->setLabel( part.partLabel ); - currentPartition->fileSystem().setLabel( part.partLabel ); + part->setLabel( entry.partLabel ); + part->fileSystem().setLabel( entry.partLabel ); } - if ( !part.partUUID.isEmpty() ) + if ( !entry.partUUID.isEmpty() ) { - currentPartition->setUUID( part.partUUID ); + part->setUUID( entry.partUUID ); } - if ( !part.partType.isEmpty() ) + if ( !entry.partType.isEmpty() ) { #if defined( WITH_KPMCORE42API ) - currentPartition->setType( part.partType ); + part->setType( entry.partType ); #else cWarning() << "Ignoring type; requires KPMcore >= 4.2.0."; #endif } - if ( part.partAttributes ) + if ( entry.partAttributes ) { #if defined( WITH_KPMCORE42API ) - currentPartition->setAttributes( part.partAttributes ); + part->setAttributes( entry.partAttributes ); #else cWarning() << "Ignoring attributes; requires KPMcore >= 4.2.0."; #endif } - if ( !part.partFeatures.isEmpty() ) + if ( !entry.partFeatures.isEmpty() ) { #if defined( WITH_KPMCORE42API ) - for ( const auto& k : part.partFeatures.keys() ) + for ( const auto& k : entry.partFeatures.keys() ) { - currentPartition->fileSystem().addFeature( k, part.partFeatures.value( k ) ); + part->fileSystem().addFeature( k, entry.partFeatures.value( k ) ); } #else cWarning() << "Ignoring features; requires KPMcore >= 4.2.0."; @@ -333,9 +306,9 @@ PartitionLayout::execute( Device* dev, } // 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; + partList.append( part ); + currentSector += sectors; + availableSectors -= sectors; } return partList; diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 79dff1697..9720ab765 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -44,8 +44,24 @@ public: /// @brief All-zeroes PartitionEntry PartitionEntry(); - /// @brief Parse @p size, @p min and @p max to their respective member variables - PartitionEntry( const QString& size, const QString& min, const QString& max ); + /// @brief Parse @p mountPoint, @p size, @p minSize and @p maxSize to their respective member variables + PartitionEntry( const QString& mountPoint, + const QString& size, + const QString& minSize = QString(), + const QString& maxSize = QString() ); + /// @brief All-field PartitionEntry + PartitionEntry( const QString& label, + const QString& uuid, + const QString& type, + quint64 attributes, + const QString& mountPoint, + const QString& fs, + const QVariantMap& features, + const QString& size, + const QString& minSize = QString(), + const QString& maxSize = QString() ); + /// @brief Copy PartitionEntry + PartitionEntry( const PartitionEntry& e ); bool isValid() const { @@ -59,36 +75,22 @@ public: }; PartitionLayout(); - PartitionLayout( PartitionEntry entry ); PartitionLayout( const PartitionLayout& layout ); ~PartitionLayout(); - bool addEntry( PartitionEntry entry ); - bool addEntry( const QString& mountPoint, - const QString& size, - const QString& min = QString(), - const QString& max = QString() ); - bool addEntry( const QString& label, - const QString& uuid, - const QString& type, - quint64 attributes, - const QString& mountPoint, - const QString& fs, - const QVariantMap& features, - const QString& size, - const QString& min = QString(), - const QString& max = QString() ); + void init( const QVariantList& config ); + bool addEntry( const PartitionEntry& entry ); /** * @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, - PartitionNode* parent, - const PartitionRole& role ); + QList< Partition* > createPartitions( Device* dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ); private: FileSystem::Type m_defaultFsType; diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index a91c9a8e1..35aec51e4 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -736,14 +736,12 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) return; } + // This will be deleted by the second lambda, below. QString* homePartitionPath = new QString(); - bool doReuseHomePartition = m_reuseHomeCheckBox->isChecked(); - // NOTE: using by-ref captures because we need to write homePartitionPath and - // doReuseHomePartition *after* the device revert, for later use. ScanningDialog::run( QtConcurrent::run( - [this, current]( QString* homePartitionPath, bool doReuseHomePartition ) { + [this, current, homePartitionPath]( bool doReuseHomePartition ) { QMutexLocker locker( &m_coreMutex ); if ( m_core->isDirty() ) @@ -823,9 +821,8 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) } } }, - homePartitionPath, - doReuseHomePartition ), - [=] { + m_reuseHomeCheckBox->isChecked() ), + [this, homePartitionPath] { m_reuseHomeCheckBox->setVisible( !homePartitionPath->isEmpty() ); if ( !homePartitionPath->isEmpty() ) m_reuseHomeCheckBox->setText( tr( "Reuse %1 as home partition for %2." ) @@ -906,7 +903,9 @@ ChoicePage::updateDeviceStatePreview() m_beforePartitionBarsView->setSelectionMode( QAbstractItemView::SingleSelection ); m_beforePartitionLabelsView->setSelectionMode( QAbstractItemView::SingleSelection ); break; - default: + case InstallChoice::NoChoice: + case InstallChoice::Erase: + case InstallChoice::Manual: m_beforePartitionBarsView->setSelectionMode( QAbstractItemView::NoSelection ); m_beforePartitionLabelsView->setSelectionMode( QAbstractItemView::NoSelection ); } @@ -990,7 +989,7 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice ) m_previewAfterFrame->show(); m_previewAfterLabel->show(); - SelectionFilter filter = [this]( const QModelIndex& index ) { + SelectionFilter filter = []( const QModelIndex& index ) { return PartUtils::canBeResized( static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ) ); }; @@ -1079,7 +1078,7 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice ) } else { - SelectionFilter filter = [this]( const QModelIndex& index ) { + SelectionFilter filter = []( const QModelIndex& index ) { return PartUtils::canBeReplaced( static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ) ); }; @@ -1125,7 +1124,9 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice ) case InstallChoice::Alongside: previewSelectionMode = QAbstractItemView::SingleSelection; break; - default: + case InstallChoice::NoChoice: + case InstallChoice::Erase: + case InstallChoice::Manual: previewSelectionMode = QAbstractItemView::NoSelection; } @@ -1179,15 +1180,15 @@ ChoicePage::setupEfiSystemPartitionSelector() QComboBox* ChoicePage::createBootloaderComboBox( QWidget* parent ) { - QComboBox* bcb = new QComboBox( parent ); - bcb->setModel( m_core->bootLoaderModel() ); + QComboBox* comboForBootloader = new QComboBox( parent ); + comboForBootloader->setModel( m_core->bootLoaderModel() ); // When the chosen bootloader device changes, we update the choice in the PCM - connect( bcb, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, [this]( int newIndex ) { - QComboBox* bcb = qobject_cast< QComboBox* >( sender() ); - if ( bcb ) + connect( comboForBootloader, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, [this]( int newIndex ) { + QComboBox* bootloaderCombo = qobject_cast< QComboBox* >( sender() ); + if ( bootloaderCombo ) { - QVariant var = bcb->itemData( newIndex, BootLoaderModel::BootLoaderPathRole ); + QVariant var = bootloaderCombo->itemData( newIndex, BootLoaderModel::BootLoaderPathRole ); if ( !var.isValid() ) { return; @@ -1196,7 +1197,7 @@ ChoicePage::createBootloaderComboBox( QWidget* parent ) } } ); - return bcb; + return comboForBootloader; } @@ -1220,7 +1221,6 @@ operator<<( QDebug& s, PartitionIterator& it ) * @brief ChoicePage::setupActions happens every time a new Device* is selected in the * device picker. Sets up the text and visibility of the partitioning actions based * on the currently selected Device*, bootloader and os-prober output. - * @param currentDevice */ void ChoicePage::setupActions() diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 63227e3b7..0431e1107 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -596,14 +596,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); m_future->setFuture( future ); - if ( configurationMap.contains( "partitionLayout" ) ) - { - m_core->initLayout( configurationMap.value( "partitionLayout" ).toList() ); - } - else - { - m_core->initLayout(); - } + m_core->initLayout( configurationMap.value( "partitionLayout" ).toList() ); } diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index bfedddfca..0f8764bfd 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -154,7 +154,19 @@ defaultFileSystemType: "ext4" # If nothing is specified, LUKS is enabled in automated modes. #enableLuksAutomatedPartitioning: true -# To apply a custom partition layout, it has to be defined this way : +# Partition layout. +# +# This optional setting specifies a custom partition layout. +# +# If nothing is specified, the default partition layout is a single partition +# for root that uses 100% of the space and uses the filesystem defined by +# defaultFileSystemType. +# +# Note: the EFI system partition is prepend automatically to the layout if +# needed; the swap partition is appended to the layout if enabled (small of +# suspend). +# +# Otherwise, the partition layout is defined as follow: # # partitionLayout: # - name: "rootfs" diff --git a/src/modules/partition/tests/CreateLayoutsTests.cpp b/src/modules/partition/tests/CreateLayoutsTests.cpp index 12c19db5f..fb991fc82 100644 --- a/src/modules/partition/tests/CreateLayoutsTests.cpp +++ b/src/modules/partition/tests/CreateLayoutsTests.cpp @@ -15,10 +15,6 @@ #include "partition/KPMManager.h" #include "utils/Logger.h" -#include -#include -#include - #include #include @@ -61,12 +57,12 @@ CreateLayoutsTests::testFixedSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( QString( "/" ), QString( "5MiB" ) ) ) + if ( !layout.addEntry( { QString( "/" ), QString( "5MiB" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } - partitions = layout.execute( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); + partitions = layout.createPartitions( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); QCOMPARE( partitions.count(), 1 ); @@ -81,12 +77,12 @@ CreateLayoutsTests::testPercentSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( QString( "/" ), QString( "50%" ) ) ) + if ( !layout.addEntry( { QString( "/" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } - partitions = layout.execute( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); + partitions = layout.createPartitions( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); QCOMPARE( partitions.count(), 1 ); @@ -101,22 +97,22 @@ CreateLayoutsTests::testMixedSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( QString( "/" ), QString( "5MiB" ) ) ) + if ( !layout.addEntry( { QString( "/" ), QString( "5MiB" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } - if ( !layout.addEntry( QString( "/home" ), QString( "50%" ) ) ) + if ( !layout.addEntry( { QString( "/home" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create /home partition" ) ); } - if ( !layout.addEntry( QString( "/bkup" ), QString( "50%" ) ) ) + if ( !layout.addEntry( { QString( "/bkup" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create /bkup partition" ) ); } - partitions = layout.execute( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); + partitions = layout.createPartitions( static_cast< Device* >( &dev ), 0, dev.totalLogical(), nullptr, nullptr, role ); QCOMPARE( partitions.count(), 3 ); diff --git a/src/modules/partition/tests/CreateLayoutsTests.h b/src/modules/partition/tests/CreateLayoutsTests.h index 2ecc7b634..5953b06a7 100644 --- a/src/modules/partition/tests/CreateLayoutsTests.h +++ b/src/modules/partition/tests/CreateLayoutsTests.h @@ -10,8 +10,9 @@ #ifndef CLEARMOUNTSJOBTESTS_H #define CLEARMOUNTSJOBTESTS_H +#include "partition/KPMHelper.h" + #include -#include class CreateLayoutsTests : public QObject { diff --git a/src/modules/partition/tests/PartitionJobTests.cpp b/src/modules/partition/tests/PartitionJobTests.cpp index 326fd53bb..a453990c7 100644 --- a/src/modules/partition/tests/PartitionJobTests.cpp +++ b/src/modules/partition/tests/PartitionJobTests.cpp @@ -16,14 +16,12 @@ #include "jobs/CreatePartitionTableJob.h" #include "jobs/ResizePartitionJob.h" +#include "partition/KPMHelper.h" #include "partition/KPMManager.h" #include "partition/PartitionQuery.h" #include "utils/Logger.h" #include "utils/Units.h" -#include -#include - #include #include #include diff --git a/src/modules/partition/tests/PartitionJobTests.h b/src/modules/partition/tests/PartitionJobTests.h index c2c01088f..9e4455ddc 100644 --- a/src/modules/partition/tests/PartitionJobTests.h +++ b/src/modules/partition/tests/PartitionJobTests.h @@ -12,12 +12,7 @@ #include "JobQueue.h" -// CalaPM -#include -#include -#include -#include -#include +#include "partition/KPMHelper.h" // Qt #include