From 7cfaba2d539e609544cb4d17034a25fcad790be0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 16:39:19 -0500 Subject: [PATCH 01/10] [partition] In logging, name device nicely - Provide a convenience method that names a Partition* with the best human-readable name we can find (worst-case, spit out a pointer representation which will at least help figure out the identity of the Partition*). --- src/modules/partition/core/PartUtils.cpp | 39 ++++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index d09bcd149..c9b46e82e 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -42,6 +42,25 @@ namespace PartUtils { +static QString +convenienceName( const Partition* const candidate ) +{ + if ( !candidate->mountPoint().isEmpty() ) + return candidate->mountPoint(); + if ( !candidate->partitionPath().isEmpty() ) + return candidate->partitionPath(); + if ( !candidate->devicePath().isEmpty() ) + return candidate->devicePath(); + if ( !candidate->deviceNode().isEmpty() ) + return candidate->devicePath(); + + QString p; + QTextStream s( &p ); + s << (void *)candidate; + + return p; +} + bool canBeReplaced( Partition* candidate ) { @@ -63,12 +82,12 @@ canBeReplaced( Partition* candidate ) << QString( "(%1GB)" ).arg( requiredStorageB / 1024 / 1024 / 1024 ); cDebug() << "Storage capacity B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length(); + << "for" << convenienceName( candidate ) << " length:" << candidate->length(); if ( ok && availableStorageB > requiredStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for replace install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install."; return true; } @@ -85,7 +104,7 @@ canBeResized( Partition* candidate ) return false; } - cDebug() << "Checking if" << candidate->partitionPath() << "can be resized."; + cDebug() << "Checking if" << convenienceName( candidate ) << "can be resized."; if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) { @@ -117,7 +136,7 @@ canBeResized( Partition* candidate ) if ( table->numPrimaries() >= table->maxPrimaries() ) { - cDebug() << " .. partition table already has" + cDebug() << " .. partition table already has" << table->maxPrimaries() << "primary partitions."; return false; } @@ -139,13 +158,13 @@ canBeResized( Partition* candidate ) << QString( "(%1GB)" ).arg( advisedStorageGB ); cDebug() << "Available storage B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length() + << "for" << convenienceName( candidate ) << " length:" << candidate->length() << " sectorsUsed:" << candidate->sectorsUsed() << " fsType:" << candidate->fileSystem().name(); if ( ok && availableStorageB > advisedStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for resize + autopartition install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install."; return true; } @@ -198,7 +217,7 @@ lookForFstabEntries( const QString& partitionPath ) mountOptions.append( "noload" ); } - cDebug() << "Checking device" << partitionPath + cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; FstabEntryList fstabEntries; @@ -209,9 +228,9 @@ lookForFstabEntries( const QString& partitionPath ) if ( !exit ) // if all is well { QFile fstabFile( mountsDir.path() + "/etc/fstab" ); - + cDebug() << " .. reading" << fstabFile.fileName(); - + if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ) @@ -381,7 +400,7 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - cDebug() << "Check EFI bootable" << candidate->partitionPath() << candidate->devicePath(); + cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath(); cDebug() << " .. flags" << candidate->activeFlags(); auto flags = PartitionInfo::flags( candidate ); From 92d9c9491a4549eb0e7e60059a1db98bd0e17147 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:05:32 -0500 Subject: [PATCH 02/10] [partition] Reduce lambda-happiness - Make some methods that are called mostly as slots, actual slots, instead of going through extra lambdas. - Use QOverload<>::of for disambiguation instead of homebrew casts. --- src/modules/partition/gui/PartitionPage.cpp | 25 ++++++++------------- src/modules/partition/gui/PartitionPage.h | 10 +++++++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a2f2eab60..a8d58f1cd 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -90,22 +90,9 @@ PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) updateFromCurrentDevice(); - connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateFromCurrentDevice(); - } ); - connect( m_ui->bootLoaderComboBox, static_cast(&QComboBox::activated), - [ this ]( const QString& /* text */ ) - { - m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); - } ); - - connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateBootLoaderInstallPath(); - } ); + connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateFromCurrentDevice ); + connect( m_ui->bootLoaderComboBox, QOverload::of(&QComboBox::activated), this, &PartitionPage::updateSelectedBootLoaderIndex ); + connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateBootLoaderInstallPath ); connect( m_core, &PartitionCoreModule::isDirtyChanged, m_ui->revertButton, &QWidget::setEnabled ); @@ -512,6 +499,12 @@ PartitionPage::updateBootLoaderInstallPath() m_core->setBootLoaderInstallPath( var.toString() ); } +void +PartitionPage::updateSelectedBootLoaderIndex() +{ + m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); +} + void PartitionPage::updateFromCurrentDevice() { diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h index 8289f2cdd..75d39c9dc 100644 --- a/src/modules/partition/gui/PartitionPage.h +++ b/src/modules/partition/gui/PartitionPage.h @@ -50,6 +50,14 @@ public: int selectedDeviceIndex(); void selectDeviceByIndex( int index ); +private slots: + /// @brief Update everything when the base device changes + void updateFromCurrentDevice(); + /// @brief Update when the selected device for boot loader changes + void updateBootLoaderInstallPath(); + /// @brief Explicitly selected boot loader path + void updateSelectedBootLoaderIndex(); + private: QScopedPointer< Ui_PartitionPage > m_ui; PartitionCoreModule* m_core; @@ -67,8 +75,6 @@ private: void updatePartitionToCreate( Device*, Partition* ); void editExistingPartition( Device*, Partition* ); - void updateBootLoaderInstallPath(); - void updateFromCurrentDevice(); void updateBootLoaderIndex(); /** From 943f3fb1f912600a3ee0c9aa0116c8e6c8474932 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:10:56 -0500 Subject: [PATCH 03/10] [partition] Improve debug-logging - Use cDebug() instead of qDebug() - Be more chatty when selecting a bootloader installation path --- src/modules/partition/gui/PartitionPage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a8d58f1cd..4e1e093b1 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -56,7 +56,6 @@ #include // Qt -#include #include #include #include @@ -495,7 +494,7 @@ PartitionPage::updateBootLoaderInstallPath() QVariant var = m_ui->bootLoaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); if ( !var.isValid() ) return; - qDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); + cDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); m_core->setBootLoaderInstallPath( var.toString() ); } @@ -503,6 +502,7 @@ void PartitionPage::updateSelectedBootLoaderIndex() { m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); + cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex; } void From b4cefff975138e621d9a9437891c9d1b09616b74 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:21:36 -0500 Subject: [PATCH 04/10] [partition] Avoid heap-wrangling - The CreatePartitionDialog doesn't need to be on the heap, it's modal here. Avoid QPointer weirdness as well. --- src/modules/partition/gui/PartitionPage.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 4e1e093b1..5b8f17fd0 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -362,18 +362,18 @@ PartitionPage::onCreateClicked() if ( !checkCanCreate( model->device() ) ) return; - QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(), - partition->parent(), - nullptr, - getCurrentUsedMountpoints(), - this ); - dlg->initFromFreeSpace( partition ); - if ( dlg->exec() == QDialog::Accepted ) + CreatePartitionDialog dlg( + model->device(), + partition->parent(), + nullptr, + getCurrentUsedMountpoints(), + this ); + dlg.initFromFreeSpace( partition ); + if ( dlg.exec() == QDialog::Accepted ) { - Partition* newPart = dlg->createPartition(); - m_core->createPartition( model->device(), newPart, dlg->newFlags() ); + Partition* newPart = dlg.createPartition(); + m_core->createPartition( model->device(), newPart, dlg.newFlags() ); } - delete dlg; } void From 90eb6afd528da0f7abf8c4dac3a3ea324b28d0a0 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:18:02 +0100 Subject: [PATCH 05/10] [partition] move parseSizeString() function to PartUtils In order to be able to parse partition size strings using the same functions across the partition module, the parseSizeString() function is exported to the PartUtils namespace. Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 59 +++++++++++++++++-- src/modules/partition/core/PartUtils.h | 17 ++++++ .../partition/core/PartitionLayout.cpp | 54 +---------------- src/modules/partition/core/PartitionLayout.h | 15 ++--- 4 files changed, 78 insertions(+), 67 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index d09bcd149..856af4799 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -2,6 +2,7 @@ * * Copyright 2015-2016, Teo Mrnjavac * Copyright 2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -117,7 +118,7 @@ canBeResized( Partition* candidate ) if ( table->numPrimaries() >= table->maxPrimaries() ) { - cDebug() << " .. partition table already has" + cDebug() << " .. partition table already has" << table->maxPrimaries() << "primary partitions."; return false; } @@ -198,7 +199,7 @@ lookForFstabEntries( const QString& partitionPath ) mountOptions.append( "noload" ); } - cDebug() << "Checking device" << partitionPath + cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; FstabEntryList fstabEntries; @@ -209,9 +210,9 @@ lookForFstabEntries( const QString& partitionPath ) if ( !exit ) // if all is well { QFile fstabFile( mountsDir.path() + "/etc/fstab" ); - + cDebug() << " .. reading" << fstabFile.fileName(); - + if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ) @@ -458,6 +459,56 @@ findFS( QString fsName, FileSystem::Type* fsType ) return fsName; } +double +parseSizeString( const QString& sizeString, SizeUnit* unit ) +{ + double value; + bool ok; + QString valueString; + QString unitString; + + QRegExp rx( "[KkMmGg%]" ); + int pos = rx.indexIn( sizeString ); + if (pos > 0) + { + valueString = sizeString.mid( 0, pos ); + unitString = sizeString.mid( pos ); + } + else + valueString = sizeString; + + value = valueString.toDouble( &ok ); + if ( !ok ) + { + /* + * In case the conversion fails, a size of 100% allows a few cases to pass + * anyway (e.g. when it is the last partition of the layout) + */ + *unit = SizeUnit::Percent; + return 100.0L; + } + + if ( unitString.length() > 0 ) + { + if ( unitString.at(0) == '%' ) + *unit = SizeUnit::Percent; + else if ( unitString.at(0).toUpper() == 'K' ) + *unit = SizeUnit::KiB; + else if ( unitString.at(0).toUpper() == 'M' ) + *unit = SizeUnit::MiB; + else if ( unitString.at(0).toUpper() == 'G' ) + *unit = SizeUnit::GiB; + else + *unit = SizeUnit::Byte; + } + else + { + *unit = SizeUnit::Byte; + } + + return value; +} + } // nmamespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index c7da86c06..35c78f061 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -2,6 +2,7 @@ * * Copyright 2015-2016, Teo Mrnjavac * Copyright 2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,14 @@ class Partition; namespace PartUtils { +enum SizeUnit +{ + Percent = 0, + Byte, + KiB, + MiB, + GiB +}; /** * @brief canBeReplaced checks whether the given Partition satisfies the criteria @@ -86,6 +95,14 @@ bool isEfiBootable( const Partition* candidate ); * its value is FileSystem::Unknown if @p fsName is not recognized. */ QString findFS( QString fsName, FileSystem::Type* fsType ); + +/** + * @brief Parse a partition size string and return its value and unit used. + * @param sizeString the string to parse. + * @param unit pointer to a SizeUnit variable for storing the parsed unit. + * @return the size value, as parsed from the input string. + */ +double parseSizeString( const QString& sizeString, SizeUnit* unit ); } #endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 39341fddd..287c19e41 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -75,61 +75,11 @@ PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) m_partLayout.append( entry ); } -static double -parseSizeString( const QString& sizeString, PartitionLayout::SizeUnit* unit ) -{ - double value; - bool ok; - QString valueString; - QString unitString; - - QRegExp rx( "[KkMmGg%]" ); - int pos = rx.indexIn( sizeString ); - if (pos > 0) - { - valueString = sizeString.mid( 0, pos ); - unitString = sizeString.mid( pos ); - } - else - valueString = sizeString; - - value = valueString.toDouble( &ok ); - if ( !ok ) - { - /* - * In case the conversion fails, a size of 100% allows a few cases to pass - * anyway (e.g. when it is the last partition of the layout) - */ - *unit = PartitionLayout::SizeUnit::Percent; - return 100; - } - - if ( unitString.length() > 0 ) - { - if ( unitString.at(0) == '%' ) - *unit = PartitionLayout::SizeUnit::Percent; - else if ( unitString.at(0).toUpper() == 'K' ) - *unit = PartitionLayout::SizeUnit::KiB; - else if ( unitString.at(0).toUpper() == 'M' ) - *unit = PartitionLayout::SizeUnit::MiB; - else if ( unitString.at(0).toUpper() == 'G' ) - *unit = PartitionLayout::SizeUnit::GiB; - else - *unit = PartitionLayout::SizeUnit::Byte; - } - else - { - *unit = PartitionLayout::SizeUnit::Byte; - } - - return value; -} - PartitionLayout::PartitionEntry::PartitionEntry(const QString& size, const QString& min) { - partSize = parseSizeString( size , &partSizeUnit ); + partSize = PartUtils::parseSizeString( size , &partSizeUnit ); if ( !min.isEmpty() ) - partMinSize = parseSizeString( min , &partMinSizeUnit ); + partMinSize = PartUtils::parseSizeString( min , &partMinSizeUnit ); } void diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 999e10425..ab597734c 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -20,6 +20,8 @@ #ifndef PARTITIONLAYOUT_H #define PARTITIONLAYOUT_H +#include "core/PartUtils.h" + #include "Typedefs.h" // KPMcore @@ -36,24 +38,15 @@ class PartitionLayout { public: - enum SizeUnit - { - Percent = 0, - Byte, - KiB, - MiB, - GiB - }; - struct PartitionEntry { QString partLabel; QString partMountPoint; FileSystem::Type partFileSystem = FileSystem::Unknown; double partSize = 0.0L; - SizeUnit partSizeUnit = Percent; + PartUtils::SizeUnit partSizeUnit = PartUtils::SizeUnit::Percent; double partMinSize = 0.0L; - SizeUnit partMinSizeUnit = Percent; + PartUtils::SizeUnit partMinSizeUnit = PartUtils::SizeUnit::Percent; /// @brief All-zeroes PartitionEntry PartitionEntry() {}; From c3ccc0de0e910a2fe0d36b59713afaaafe593a78 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:31:30 +0100 Subject: [PATCH 06/10] [libcalamares] Add a KiB unit This commit creates a _KiB operator for future use by the partition module. It also fixes a typo in one instance of MiBtoBytes(), requiring a couple extra fixes. Signed-off-by: Arnaud Ferraris --- src/libcalamares/utils/Units.h | 21 +++++++++++++++++-- src/modules/fsresizer/ResizeFSJob.cpp | 2 +- .../partition/tests/PartitionJobTests.cpp | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index efc100d59..34f80b17f 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2017, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,10 +25,16 @@ namespace CalamaresUtils { +/** User defined literals, 1_KiB is 1 KibiByte (= 2^10 bytes) */ +constexpr qint64 operator ""_KiB( unsigned long long m ) +{ + return qint64(m) * 1024; +} + /** User defined literals, 1_MiB is 1 MibiByte (= 2^20 bytes) */ constexpr qint64 operator ""_MiB( unsigned long long m ) { - return qint64(m) * 1024 * 1024; + return operator ""_KiB(m) * 1024; } /** User defined literals, 1_GiB is 1 GibiByte (= 2^30 bytes) */ @@ -36,6 +43,11 @@ constexpr qint64 operator ""_GiB( unsigned long long m ) return operator ""_MiB(m) * 1024; } +constexpr qint64 KiBtoBytes( unsigned long long m ) +{ + return operator ""_KiB( m ); +} + constexpr qint64 MiBtoBytes( unsigned long long m ) { return operator ""_MiB( m ); @@ -46,7 +58,12 @@ constexpr qint64 GiBtoBytes( unsigned long long m ) return operator ""_GiB( m ); } -constexpr qint64 MiBToBytes( double m ) +constexpr qint64 KiBtoBytes( double m ) +{ + return qint64(m * 1024); +} + +constexpr qint64 MiBtoBytes( double m ) { return qint64(m * 1024 * 1024); } diff --git a/src/modules/fsresizer/ResizeFSJob.cpp b/src/modules/fsresizer/ResizeFSJob.cpp index 6394075ba..2ce9eba70 100644 --- a/src/modules/fsresizer/ResizeFSJob.cpp +++ b/src/modules/fsresizer/ResizeFSJob.cpp @@ -80,7 +80,7 @@ ResizeFSJob::RelativeSize::apply( qint64 totalSectors, qint64 sectorSize ) case unit_t::None: return -1; case unit_t::Absolute: - return CalamaresUtils::MiBtoBytes( value() ) / sectorSize; + return CalamaresUtils::MiBtoBytes( static_cast( value() ) ) / sectorSize; case unit_t::Percent: if ( value() == 100 ) return totalSectors; // Common-case, avoid futzing around diff --git a/src/modules/partition/tests/PartitionJobTests.cpp b/src/modules/partition/tests/PartitionJobTests.cpp index d3fd67c12..6a7e2ab72 100644 --- a/src/modules/partition/tests/PartitionJobTests.cpp +++ b/src/modules/partition/tests/PartitionJobTests.cpp @@ -349,7 +349,8 @@ PartitionJobTests::testResizePartition() // Make the test data file smaller than the full size of the partition to // accomodate for the file system overhead - const QByteArray testData = generateTestData( CalamaresUtils::MiBtoBytes( qMin( oldSizeMB, newSizeMB ) ) * 3 / 4 ); + const unsigned long long minSizeMB = qMin( oldSizeMB, newSizeMB ); + const QByteArray testData = generateTestData( CalamaresUtils::MiBtoBytes( minSizeMB ) * 3 / 4 ); const QString testName = "test.data"; // Setup: create the test partition From a5258f07a1896217af4e82e92aa5396e0d319e5a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:36:29 +0100 Subject: [PATCH 07/10] [partition] move bytesToSectors() and sizeToSectors() to PartUtils In order to allow the use of these functions across the whole partition module and keep all partition size-related functions in the same namespace, this commit moves them to PartUtils. Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 34 +++++++++++++++++++ src/modules/partition/core/PartUtils.h | 28 +++++++++++++++ .../partition/core/PartitionActions.cpp | 23 ++----------- src/modules/partition/core/PartitionActions.h | 2 -- .../partition/core/PartitionLayout.cpp | 33 ++---------------- 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 856af4799..75a33bf94 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -459,6 +459,33 @@ findFS( QString fsName, FileSystem::Type* fsType ) return fsName; } +static qint64 +sizeToBytes( double size, SizeUnit unit, qint64 totalSize ) +{ + qint64 bytes; + + switch ( unit ) + { + case SizeUnit::Percent: + bytes = qint64( static_cast( totalSize ) * size / 100.0L ); + break; + case SizeUnit::KiB: + bytes = CalamaresUtils::KiBtoBytes(size); + break; + case SizeUnit::MiB: + bytes = CalamaresUtils::MiBtoBytes(size); + break; + case SizeUnit::GiB: + bytes = CalamaresUtils::GiBtoBytes(size); + break; + default: + bytes = size; + break; + } + + return bytes; +} + double parseSizeString( const QString& sizeString, SizeUnit* unit ) { @@ -509,6 +536,13 @@ parseSizeString( const QString& sizeString, SizeUnit* unit ) return value; } +qint64 +sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ) +{ + qint64 bytes = sizeToBytes( size, unit, totalSectors * logicalSize ); + return bytesToSectors( static_cast( bytes ), logicalSize ); +} + } // nmamespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 35c78f061..8b811fd6d 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -22,6 +22,7 @@ #define PARTUTILS_H #include "OsproberEntry.h" +#include "utils/Units.h" // KPMcore #include @@ -34,6 +35,8 @@ class Partition; namespace PartUtils { +using CalamaresUtils::MiBtoBytes; + enum SizeUnit { Percent = 0, @@ -103,6 +106,31 @@ QString findFS( QString fsName, FileSystem::Type* fsType ); * @return the size value, as parsed from the input string. */ double parseSizeString( const QString& sizeString, SizeUnit* unit ); + +/** + * @brief Convert a partition size to a sectors count. + * @param size the partition size. + * @param unit the partition size unit. + * @param totalSectors the total number of sectors of the selected drive. + * @param logicalSize the sector size, in bytes. + * @return the number of sectors to be used for the given partition size. + */ +qint64 sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ); + +constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) +{ + qint64 blocks = bytes / blocksize; + + if ( blocks * blocksize != bytes ) + ++blocks; + return blocks * blocksize; +} + +constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) +{ + return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1ULL) ) / blocksize; +} + } #endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index a135b758f..01e794ff6 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -2,6 +2,7 @@ * * Copyright 2014-2017, Teo Mrnjavac * Copyright 2017-2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,8 +39,6 @@ namespace PartitionActions { -using CalamaresUtils::GiBtoBytes; -using CalamaresUtils::MiBtoBytes; using CalamaresUtils::operator""_GiB; using CalamaresUtils::operator""_MiB; @@ -82,22 +81,6 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) return suggestedSwapSizeB; } -constexpr qint64 -alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) -{ - qint64 blocks = bytes / blocksize; - - if ( blocks * blocksize != bytes ) - ++blocks; - return blocks * blocksize; -} - -qint64 -bytesToSectors( qint64 bytes, qint64 blocksize ) -{ - return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1) ) / blocksize; -} - void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { @@ -117,11 +100,11 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors // before that one, numbered 0..2047). - qint64 firstFreeSector = bytesToSectors( empty_space_sizeB, dev->logicalSize() ); + qint64 firstFreeSector = PartUtils::bytesToSectors( empty_space_sizeB, dev->logicalSize() ); if ( isEfi ) { - qint64 efiSectorCount = bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); + qint64 efiSectorCount = PartUtils::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); Q_ASSERT( efiSectorCount > 0 ); // Since sectors count from 0, and this partition is created starting diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index 179b835ab..d17852b63 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -75,8 +75,6 @@ namespace Choices } // namespace Choices -qint64 bytesToSectors( qint64 bytes, qint64 blocksize ); - /** * @brief doAutopartition sets up an autopartitioning operation on the given Device. * @param core a pointer to the PartitionCoreModule instance. diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 287c19e41..4f62db7d6 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -107,35 +107,6 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons m_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, @@ -155,8 +126,8 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, Partition *currentPartition = nullptr; // Calculate partition size - size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); - minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); + size = PartUtils::sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); + minSize = PartUtils::sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); if ( size < minSize ) size = minSize; if ( size > availableSize ) From 982840bafd234bf462f74739008c516a95b6b00a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:46:25 +0100 Subject: [PATCH 08/10] [partition] Allow a configurable EFI System Partition size As requested, this commit adds a new configuration option to the partition.conf file, name `efiSystemPartitionSize`. When this option is absent, the default size of 300MiB will be used. Fixes #1090 Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 9 +++++++++ src/modules/partition/core/PartUtils.h | 8 ++++++++ src/modules/partition/core/PartitionActions.cpp | 14 ++++++++++++-- src/modules/partition/gui/PartitionViewStep.cpp | 8 +++++++- src/modules/partition/partition.conf | 4 ++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 75a33bf94..4e8b7e8ba 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -536,6 +536,15 @@ parseSizeString( const QString& sizeString, SizeUnit* unit ) return value; } +qint64 +parseSizeString( const QString& sizeString, qint64 totalSize ) +{ + SizeUnit unit; + double value = parseSizeString( sizeString, &unit ); + + return sizeToBytes( value, unit, totalSize ); +} + qint64 sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ) { diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 8b811fd6d..0ad559a60 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -107,6 +107,14 @@ QString findFS( QString fsName, FileSystem::Type* fsType ); */ double parseSizeString( const QString& sizeString, SizeUnit* unit ); +/** + * @brief Parse a partition size string and return its value in bytes. + * @param sizeString the string to parse. + * @param totalSize the size of the selected drive (used when the size is expressed in %) + * @return the size value in bytes. + */ +qint64 parseSizeString( const QString& sizeString, qint64 totalSize ); + /** * @brief Convert a partition size to a sectors count. * @param size the partition size. diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 01e794ff6..4172002fa 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -29,6 +29,7 @@ #include "utils/Units.h" #include "utils/NamedEnum.h" +#include "GlobalStorage.h" #include "JobQueue.h" #include "utils/Logger.h" @@ -84,6 +85,7 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) defaultFsType = "ext4"; @@ -92,10 +94,18 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // Partition sizes are expressed in MiB, should be multiples of // the logical sector size (usually 512B). EFI starts with 2MiB - // empty and a 300MiB EFI boot partition, while BIOS starts at + // empty and a EFI boot partition, while BIOS starts at // the 1MiB boundary (usually sector 2048). - int uefisys_part_sizeB = isEfi ? 300_MiB : 0_MiB; int empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; + int uefisys_part_sizeB = 0_MiB; + + if ( isEfi ) + { + if ( gs->contains( "efiSystemPartitionSize" ) ) + uefisys_part_sizeB = PartUtils::parseSizeString( gs->value( "efiSystemPartitionSize" ).toString(), dev->capacity() ); + else + uefisys_part_sizeB = 300_MiB; + } // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 6fc8b0129..ffeb8c055 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -3,7 +3,7 @@ * Copyright 2014, Aurélien Gâteau * Copyright 2014-2017, Teo Mrnjavac * Copyright 2018, Adriaan de Groot - * Copyright 2019, Collabora Ltd + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -489,6 +489,12 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) efiSP = QStringLiteral( "/boot/efi" ); gs->insert( "efiSystemPartition", efiSP ); + // Read and parse key efiSystemPartitionSize + if ( configurationMap.contains( "efiSystemPartitionSize" ) ) + { + gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) ); + } + // SWAP SETTINGS // // This is a bit convoluted because there's legacy settings to handle as well diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index f812b67aa..66f40020c 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -3,6 +3,10 @@ # etc.) use just /boot. efiSystemPartition: "/boot/efi" +# This optional setting specifies the size of the EFI system partition. +# If nothing is specified, the default size of 300MiB will be used. +# efiSystemPartitionSize: 300M + # In autogenerated partitioning, allow the user to select a swap size? # If there is exactly one choice, no UI is presented, and the user # cannot make a choice -- this setting is used. If there is more than From 3e067e617e9fed5e86a39aa87f861114da61f124 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 28 Feb 2019 10:26:17 -0500 Subject: [PATCH 09/10] [partition] Add accessor and documentation to BootLoaderInstallPath --- src/modules/partition/core/PartitionCoreModule.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index c48c1562c..743f9c178 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -154,6 +154,9 @@ public: void setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ); + /// @brief Retrieve the path where the bootloader will be installed + QString bootLoaderInstallPath() const { return m_bootLoaderInstallPath; } + /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); void initLayout(); From 2b149fb944da8d975c05d562ab55adaa9dec25bb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 1 Mar 2019 06:56:52 -0500 Subject: [PATCH 10/10] [partition] Uncomment updateButtons() - This was commented out to combat the crash in device->type() - I believe the crash was caused by double-deletion, which was fixed in 2092ec3c9a0a37553fd061f423df9d29fe55ab80 by not re- parenting an immutable copy of something. - Restore the button-fix, since we need that to keep the *create* button in-sync with the selected partition. FIXES #1097 --- src/modules/partition/gui/PartitionPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a2f2eab60..2743ec53a 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -581,7 +581,7 @@ void PartitionPage::onPartitionModelReset() { m_ui->partitionTreeView->expandAll(); - // updateButtons(); + updateButtons(); updateBootLoaderIndex(); }