diff --git a/CMakeModules/CalamaresAddTest.cmake b/CMakeModules/CalamaresAddTest.cmake index f1f6fdf3f..36be0f03e 100644 --- a/CMakeModules/CalamaresAddTest.cmake +++ b/CMakeModules/CalamaresAddTest.cmake @@ -34,7 +34,7 @@ function( calamares_add_test ) # parse arguments (name needs to be saved before passing ARGN into the macro) set( NAME ${ARGV0} ) set( options GUI ) - set( multiValueArgs SOURCES LIBRARIES ) + set( multiValueArgs SOURCES LIBRARIES DEFINITIONS ) cmake_parse_arguments( TEST "${options}" "" "${multiValueArgs}" ${ARGN} ) set( TEST_NAME ${NAME} ) @@ -50,7 +50,7 @@ function( calamares_add_test ) Qt5::Test ) calamares_automoc( ${TEST_NAME} ) - target_compile_definitions( ${TEST_NAME} PRIVATE -DBUILD_AS_TEST ) + target_compile_definitions( ${TEST_NAME} PRIVATE -DBUILD_AS_TEST ${TEST_DEFINITIONS} ) if( TEST_GUI ) target_link_libraries( ${TEST_NAME} calamaresui Qt5::Gui ) endif() diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 803c46870..156ab2cc6 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -44,7 +44,9 @@ set( libSources network/Manager.cpp # Partition service + partition/Mount.cpp partition/PartitionSize.cpp + partition/Sync.cpp # Utility service utils/CalamaresUtilsSystem.cpp @@ -110,6 +112,38 @@ if( Qt5Xml_FOUND ) list( APPEND OPTIONAL_PUBLIC_LIBRARIES Qt5::Network Qt5::Xml ) endif() +### OPTIONAL KPMcore support +# +# +find_package( KPMcore 3.3 ) +set_package_properties( + KPMcore PROPERTIES + URL "https://invent.kde.org/kde/kpmcore" + DESCRIPTION "KDE Partitioning library" + TYPE RECOMMENDED + PURPOSE "For partitioning service" +) + +if ( KPMcore_FOUND ) + find_package( Qt5 REQUIRED DBus ) # Needed for KPMCore + find_package( KF5 REQUIRED I18n WidgetsAddons ) # Needed for KPMCore + + if( KPMcore_VERSION VERSION_GREATER_EQUAL "4.0" ) + add_definitions( -DWITH_KPMCORE4API ) # kpmcore 4 with new API + elseif( KPMcore_VERSION VERSION_GREATER "3.3.70" ) + message( FATAL_ERROR "KPMCore beta versions ${KPMcore_VERSION} not supported" ) + endif() + + include_directories( ${KPMCORE_INCLUDE_DIR} ) + list( APPEND libSources + partition/FileSystem.cpp + partition/KPMManager.cpp + partition/PartitionIterator.cpp + partition/PartitionQuery.cpp + ) + list( APPEND OPTIONAL_PRIVATE_LIBRARIES kpmcore ) +endif() + ### LIBRARY # # diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index 2690769db..44382fb91 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -36,12 +36,13 @@ public: : QThread( queue ) , m_queue( queue ) , m_jobIndex( 0 ) + , m_jobCount( 0 ) { } virtual ~JobThread() override; - void setJobs( const JobList& jobs ) + void setJobs( JobList&& jobs ) { m_jobs = jobs; @@ -73,7 +74,7 @@ public: } emitProgress(); - cDebug() << "Starting" << ( anyFailed ? "EMERGENCY JOB" : "job" ) << job->prettyName(); + cDebug() << "Starting" << ( anyFailed ? "EMERGENCY JOB" : "job" ) << job->prettyName() << " (there are" << m_jobs.count() << " left)"; connect( job.data(), &Job::progress, this, &JobThread::emitProgress ); JobResult result = job->exec(); if ( !anyFailed && !result ) @@ -103,6 +104,7 @@ private: QList< qreal > m_jobWeights; JobQueue* m_queue; int m_jobIndex; + int m_jobCount; void emitProgress( qreal jobPercent = 0 ) { @@ -193,7 +195,7 @@ void JobQueue::start() { Q_ASSERT( !m_thread->isRunning() ); - m_thread->setJobs( m_jobs ); + m_thread->setJobs( std::move( m_jobs ) ); m_jobs.clear(); m_thread->start(); } diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp index 132a9dcf5..393958664 100644 --- a/src/libcalamares/PythonJobApi.cpp +++ b/src/libcalamares/PythonJobApi.cpp @@ -22,6 +22,7 @@ #include "GlobalStorage.h" #include "JobQueue.h" #include "PythonHelper.h" +#include "partition/Mount.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include "utils/String.h" @@ -63,10 +64,10 @@ mount( const std::string& device_path, const std::string& filesystem_name, const std::string& options ) { - return CalamaresUtils::System::instance()->mount( QString::fromStdString( device_path ), - QString::fromStdString( mount_point ), - QString::fromStdString( filesystem_name ), - QString::fromStdString( options ) ); + return CalamaresUtils::Partition::mount( QString::fromStdString( device_path ), + QString::fromStdString( mount_point ), + QString::fromStdString( filesystem_name ), + QString::fromStdString( options ) ); } diff --git a/src/libcalamares/partition/FileSystem.cpp b/src/libcalamares/partition/FileSystem.cpp new file mode 100644 index 000000000..fbbe48581 --- /dev/null +++ b/src/libcalamares/partition/FileSystem.cpp @@ -0,0 +1,74 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015-2016, Teo Mrnjavac + * Copyright 2018-2019 Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "FileSystem.h" + +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +QString +prettyNameForFileSystemType( FileSystem::Type t ) +{ + switch ( t ) + { + case FileSystem::Unknown: + return QObject::tr( "unknown" ); + case FileSystem::Extended: + return QObject::tr( "extended" ); + case FileSystem::Unformatted: + return QObject::tr( "unformatted" ); + case FileSystem::LinuxSwap: + return QObject::tr( "swap" ); + case FileSystem::Fat16: + case FileSystem::Fat32: + case FileSystem::Ntfs: + case FileSystem::Xfs: + case FileSystem::Jfs: + case FileSystem::Hfs: + case FileSystem::Ufs: + case FileSystem::Hpfs: + case FileSystem::Luks: + case FileSystem::Ocfs2: + case FileSystem::Zfs: + case FileSystem::Nilfs2: + return FileSystem::nameForType( t ).toUpper(); + case FileSystem::ReiserFS: + return "ReiserFS"; + case FileSystem::Reiser4: + return "Reiser4"; + case FileSystem::HfsPlus: + return "HFS+"; + case FileSystem::Btrfs: + return "Btrfs"; + case FileSystem::Exfat: + return "exFAT"; + case FileSystem::Lvm2_PV: + return "LVM PV"; + default: + return FileSystem::nameForType( t ); + } +} + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/FileSystem.h b/src/libcalamares/partition/FileSystem.h new file mode 100644 index 000000000..258515d3c --- /dev/null +++ b/src/libcalamares/partition/FileSystem.h @@ -0,0 +1,65 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015-2016, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +/* + * NOTE: this functionality is only available when Calamares is compiled + * with KPMcore support. + */ + +#ifndef PARTITION_FILESYSTEM_H +#define PARTITION_FILESYSTEM_H + +#include + +namespace CalamaresUtils +{ +namespace Partition +{ +QString prettyNameForFileSystemType( FileSystem::Type t ); + +static inline QString +untranslatedFS( FileSystem& fs ) +{ + return fs.name( { QStringLiteral( "C" ) } ); +} + +static inline QString +untranslatedFS( FileSystem* fs ) +{ + return fs ? untranslatedFS( *fs ) : QString(); +} + +static inline QString +userVisibleFS( FileSystem& fs ) +{ + return fs.name(); +} + +static inline QString +userVisibleFS( FileSystem* fs ) +{ + return fs ? userVisibleFS( *fs ) : QString(); +} + + +} // namespace Partition +} // namespace CalamaresUtils + +#endif // PARTITION_PARTITIONQUERY_H diff --git a/src/libcalamares/partition/KPMManager.cpp b/src/libcalamares/partition/KPMManager.cpp new file mode 100644 index 000000000..efc5f0003 --- /dev/null +++ b/src/libcalamares/partition/KPMManager.cpp @@ -0,0 +1,128 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "KPMManager.h" + +#include "utils/Logger.h" + +#include +#include +#if defined( WITH_KPMCORE4API ) +#include +#endif + + +#include + + +namespace CalamaresUtils +{ +namespace Partition +{ +class InternalManager +{ +public: + InternalManager(); + ~InternalManager(); +}; + +static bool s_kpm_loaded = false; + +/* + * We have one living InternalManager object at a time. + * It is managed by shared_ptr<>s help by KPMManager + * objects, but since we can create KPMManager objects + * independent of each other, all of which share ownership + * of the same InternalManager, hang on to one extra reference + * to the InternalManager so we can hand it out in getInternal(). + */ +static std::weak_ptr< InternalManager > s_backend; + +InternalManager::InternalManager() +{ + cDebug() << "KPMCore backend starting .."; + + Q_ASSERT( s_backend.expired() ); + + if ( !s_kpm_loaded ) + { + QByteArray backendName = qgetenv( "KPMCORE_BACKEND" ); + if ( !CoreBackendManager::self()->load( backendName.isEmpty() ? CoreBackendManager::defaultBackendName() + : backendName ) ) + { + cWarning() << "Failed to load backend plugin" << backendName; + } + else + { + auto* backend_p = CoreBackendManager::self()->backend(); + cDebug() << Logger::SubEntry << "Backend @" << (void*)backend_p << backend_p->id() << backend_p->version(); + s_kpm_loaded = true; + } + } +} + +InternalManager::~InternalManager() +{ + cDebug() << "Cleaning up KPMCore backend .."; + +#if defined( WITH_KPMCORE4API ) + auto backend_p = CoreBackendManager::self()->backend(); + if ( backend_p ) + { + ExternalCommand::stopHelper(); + } +#endif +} + +std::shared_ptr< InternalManager > +getInternal() +{ + if ( s_backend.expired() ) + { + auto p = std::make_shared< InternalManager >(); + s_backend = p; + return p; + } + return s_backend.lock(); +} + +KPMManager::KPMManager() + : m_d( getInternal() ) +{ + cDebug() << "KPMManager" << s_backend.use_count() << "created."; +} + +KPMManager::~KPMManager() +{ + cDebug() << "KPMManager" << s_backend.use_count() << "being destroyed."; +} + +KPMManager::operator bool() const +{ + return s_kpm_loaded; +} + +CoreBackend* +KPMManager::backend() const +{ + return s_kpm_loaded ? CoreBackendManager::self()->backend() : nullptr; +} + + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/KPMManager.h b/src/libcalamares/partition/KPMManager.h new file mode 100644 index 000000000..5f7039221 --- /dev/null +++ b/src/libcalamares/partition/KPMManager.h @@ -0,0 +1,69 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +/* + * NOTE: this functionality is only available when Calamares is compiled + * with KPMcore support. + */ + +#ifndef PARTITION_KPMMANAGER_H +#define PARTITION_KPMMANAGER_H + +#include + +class CoreBackend; + +namespace CalamaresUtils +{ +namespace Partition +{ +/// @brief Handle to KPMCore +class InternalManager; + +/** @brief KPMCore loader and cleanup + * + * A Calamares plugin that uses KPMCore should hold an object of + * this class; its only responsibility is to load KPMCore + * and to cleanly unload it on destruction (with KPMCore 4, + * also to shutdown the privileged helper application). + * + * It loads the default plugin ("parted" with KPMCore 3, "sfdisk" + * with KPMCore 4), but this can be overridden by setting the + * environment variable KPMCORE_BACKEND. Setting it to + * "dummy" will load the dummy plugin instead. + */ +class KPMManager +{ +public: + KPMManager(); + ~KPMManager(); + + /// @brief Is KPMCore loaded correctly? + operator bool() const; + + /// @brief Gets the KPMCore backend (e.g. CoreBackendManager::self()->backend() ) + CoreBackend* backend() const; + +private: + std::shared_ptr< InternalManager > m_d; +}; + +} // namespace Partition +} // namespace CalamaresUtils + +#endif // PARTITION_KPMMANAGER_H diff --git a/src/libcalamares/partition/Mount.cpp b/src/libcalamares/partition/Mount.cpp new file mode 100644 index 000000000..91fcefff5 --- /dev/null +++ b/src/libcalamares/partition/Mount.cpp @@ -0,0 +1,132 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * Copyright 2017-2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "Mount.h" + +#include "partition/Sync.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" + +#include +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +int +mount( const QString& devicePath, const QString& mountPoint, const QString& filesystemName, const QString& options ) +{ + if ( devicePath.isEmpty() || mountPoint.isEmpty() ) + { + if ( devicePath.isEmpty() ) + { + cWarning() << "Can't mount an empty device."; + } + if ( mountPoint.isEmpty() ) + { + cWarning() << "Can't mount on an empty mountpoint."; + } + + return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); + } + + QDir mountPointDir( mountPoint ); + if ( !mountPointDir.exists() ) + { + bool ok = mountPointDir.mkpath( mountPoint ); + if ( !ok ) + { + cWarning() << "Could not create mountpoint" << mountPoint; + return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); + } + } + + QStringList args = { "mount" }; + + if ( !filesystemName.isEmpty() ) + { + args << "-t" << filesystemName; + } + if ( !options.isEmpty() ) + { + if ( options.startsWith( '-' ) ) + { + args << options; + } + else + { + args << "-o" << options; + } + } + args << devicePath << mountPoint; + + auto r = CalamaresUtils::System::runCommand( args, std::chrono::seconds( 10 ) ); + sync(); + return r.getExitCode(); +} + +int +unmount( const QString& path, const QStringList& options ) +{ + auto r + = CalamaresUtils::System::runCommand( QStringList { "umount" } << options << path, std::chrono::seconds( 10 ) ); + sync(); + return r.getExitCode(); +} + +struct TemporaryMount::Private +{ + QString m_devicePath; + QTemporaryDir m_mountDir; +}; + + +TemporaryMount::TemporaryMount( const QString& devicePath, const QString& filesystemName, const QString& options ) + : m_d( new Private ) +{ + m_d->m_devicePath = devicePath; + m_d->m_mountDir.setAutoRemove( false ); + int r = mount( devicePath, m_d->m_mountDir.path(), filesystemName, options ); + if ( !r ) + { + delete m_d; + m_d = nullptr; + } +} + +TemporaryMount::~TemporaryMount() +{ + if ( m_d ) + { + unmount( m_d->m_devicePath, { "-R" } ); + delete m_d; + m_d = nullptr; + } +} + +QString +TemporaryMount::path() const +{ + return m_d ? m_d->m_mountDir.path() : QString(); +} + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/Mount.h b/src/libcalamares/partition/Mount.h new file mode 100644 index 000000000..041e7e757 --- /dev/null +++ b/src/libcalamares/partition/Mount.h @@ -0,0 +1,80 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * Copyright 2017-2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef PARTITION_MOUNT_H +#define PARTITION_MOUNT_H + +#include "DllMacro.h" + +#include +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +/** + * Runs the mount utility with the specified parameters. + * @param devicePath the path of the partition to mount. + * @param mountPoint the full path of the target mount point. + * @param filesystemName the name of the filesystem (optional). + * @param options any additional options as passed to mount -o (optional). + * If @p options starts with a dash (-) then it is passed unchanged + * and no -o option is added; this is used in handling --bind mounts. + * @returns the program's exit code, or: + * Crashed = QProcess crash + * FailedToStart = QProcess cannot start + * NoWorkingDirectory = bad arguments + */ +DLLEXPORT int mount( const QString& devicePath, + const QString& mountPoint, + const QString& filesystemName = QString(), + const QString& options = QString() ); + +/** @brief Unmount the given @p path (device or mount point). + * + * Runs umount(8) in the host system. + * + * @returns the program's exit code, or special codes like mount(). + */ +DLLEXPORT int unmount( const QString& path, const QStringList& options = QStringList() ); + +class DLLEXPORT TemporaryMount +{ +public: + TemporaryMount( const QString& devicePath, + const QString& filesystemName = QString(), + const QString& options = QString() ); + TemporaryMount( const TemporaryMount& ) = delete; + TemporaryMount& operator=( const TemporaryMount& ) = delete; + ~TemporaryMount(); + + bool isValid() const { return m_d; } + QString path() const; + +private: + struct Private; + Private* m_d = nullptr; +}; + +} // namespace Partition +} // namespace CalamaresUtils + +#endif diff --git a/src/modules/partition/core/PartitionIterator.cpp b/src/libcalamares/partition/PartitionIterator.cpp similarity index 90% rename from src/modules/partition/core/PartitionIterator.cpp rename to src/libcalamares/partition/PartitionIterator.cpp index 34471f6f2..642752163 100644 --- a/src/modules/partition/core/PartitionIterator.cpp +++ b/src/libcalamares/partition/PartitionIterator.cpp @@ -2,7 +2,7 @@ * * Copyright 2014, Aurélien Gâteau * Copyright 2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019 Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +25,19 @@ #include #include +namespace CalamaresUtils +{ +namespace Partition +{ + +using Partition = ::Partition; + PartitionIterator::PartitionIterator( PartitionTable* table ) : m_table( table ) -{} +{ +} -Partition* -PartitionIterator::operator*() const +Partition* PartitionIterator::operator*() const { return m_current; } @@ -39,7 +46,9 @@ void PartitionIterator::operator++() { if ( !m_current ) + { return; + } if ( m_current->hasChildren() ) { // Go to the first child @@ -78,18 +87,21 @@ PartitionIterator::operator==( const PartitionIterator& other ) const bool PartitionIterator::operator!=( const PartitionIterator& other ) const { - return ! ( *this == other ); + return !( *this == other ); } PartitionIterator PartitionIterator::begin( Device* device ) { if ( !device ) + { return PartitionIterator( nullptr ); - Q_ASSERT(device); + } PartitionTable* table = device->partitionTable(); if ( !table ) + { return PartitionIterator( nullptr ); + } return PartitionIterator::begin( table ); } @@ -101,7 +113,9 @@ PartitionIterator::begin( PartitionTable* table ) // Does not usually happen, but it did happen on a tiny (10MiB) disk with an MBR // partition table. if ( children.isEmpty() ) + { return it; + } it.m_current = children.first(); return it; } @@ -110,10 +124,14 @@ PartitionIterator PartitionIterator::end( Device* device ) { if ( !device ) + { return PartitionIterator( nullptr ); + } PartitionTable* table = device->partitionTable(); if ( !table ) + { return PartitionIterator( nullptr ); + } return PartitionIterator::end( table ); } @@ -123,3 +141,6 @@ PartitionIterator::end( PartitionTable* table ) { return PartitionIterator( table ); } + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/modules/partition/core/PartitionIterator.h b/src/libcalamares/partition/PartitionIterator.h similarity index 53% rename from src/modules/partition/core/PartitionIterator.h rename to src/libcalamares/partition/PartitionIterator.h index b72c2de8a..78d930cf4 100644 --- a/src/modules/partition/core/PartitionIterator.h +++ b/src/libcalamares/partition/PartitionIterator.h @@ -2,6 +2,7 @@ * * Copyright 2014, Aurélien Gâteau * Copyright 2015, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,37 +18,57 @@ * along with Calamares. If not, see . */ -#ifndef PARTITIONITERATOR_H -#define PARTITIONITERATOR_H +/* + * NOTE: this functionality is only available when Calamares is compiled + * with KPMcore support. + */ + +#ifndef PARTITION_PARTITIONITERATOR_H +#define PARTITION_PARTITIONITERATOR_H class Device; class Partition; class PartitionTable; -/** +namespace CalamaresUtils +{ +namespace Partition +{ + +/** @brief Iterator over KPMCore partitions + * * A forward-only iterator to go through the partitions of a device, * independently of whether they are primary, logical or extended. + * + * An iterator can be created from a device (then it refers to the + * partition table of that device) or a partition table. The + * partition table must remain valid throughout iteration. + * + * A nullptr is valid, for an empty iterator. */ class PartitionIterator { public: - Partition* operator*() const; + ::Partition* operator*() const; void operator++(); bool operator==( const PartitionIterator& other ) const; bool operator!=( const PartitionIterator& other ) const; - static PartitionIterator begin( Device* device ); - static PartitionIterator begin( PartitionTable* table ); - static PartitionIterator end( Device* device ); - static PartitionIterator end( PartitionTable* table ); + static PartitionIterator begin( ::Device* device ); + static PartitionIterator begin( ::PartitionTable* table ); + static PartitionIterator end( ::Device* device ); + static PartitionIterator end( ::PartitionTable* table ); private: - PartitionIterator( PartitionTable* table ); + PartitionIterator( ::PartitionTable* table ); - PartitionTable* m_table; - Partition* m_current = nullptr; + ::PartitionTable* m_table; + ::Partition* m_current = nullptr; }; -#endif /* PARTITIONITERATOR_H */ +} // namespace Partition +} // namespace CalamaresUtils + +#endif // PARTITION_PARTITIONITERATOR_H diff --git a/src/libcalamares/partition/PartitionQuery.cpp b/src/libcalamares/partition/PartitionQuery.cpp new file mode 100644 index 000000000..6693f7e6c --- /dev/null +++ b/src/libcalamares/partition/PartitionQuery.cpp @@ -0,0 +1,102 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015-2016, Teo Mrnjavac + * Copyright 2018-2019 Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "PartitionQuery.h" + +#include "PartitionIterator.h" + +#include +#include + +namespace CalamaresUtils +{ +namespace Partition +{ + +// Types from KPMCore +using ::Device; +using ::Partition; + +bool +isPartitionFreeSpace( Partition* partition ) +{ + return partition->roles().has( PartitionRole::Unallocated ); +} + + +bool +isPartitionNew( Partition* partition ) +{ +#if defined( WITH_KPMCORE4API ) + constexpr auto NewState = Partition::State::New; +#else + constexpr auto NewState = Partition::StateNew; +#endif + return partition->state() == NewState; +} + + +Partition* +findPartitionByCurrentMountPoint( const QList< Device* >& devices, const QString& mountPoint ) +{ + for ( auto device : devices ) + for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) + if ( ( *it )->mountPoint() == mountPoint ) + { + return *it; + } + return nullptr; +} + + +Partition* +findPartitionByPath( const QList< Device* >& devices, const QString& path ) +{ + if ( path.simplified().isEmpty() ) + { + return nullptr; + } + + for ( auto device : devices ) + for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) + if ( ( *it )->partitionPath() == path.simplified() ) + { + return *it; + } + return nullptr; +} + + +QList< Partition* > +findPartitions( const QList< Device* >& devices, std::function< bool( Partition* ) > criterionFunction ) +{ + 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; +} + + +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/PartitionQuery.h b/src/libcalamares/partition/PartitionQuery.h new file mode 100644 index 000000000..18eb7edd2 --- /dev/null +++ b/src/libcalamares/partition/PartitionQuery.h @@ -0,0 +1,78 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015-2016, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +/* + * NOTE: this functionality is only available when Calamares is compiled + * with KPMcore support. + */ + +#ifndef PARTITION_PARTITIONQUERY_H +#define PARTITION_PARTITIONQUERY_H + +#include + +#include + +class Device; +class Partition; + +namespace CalamaresUtils +{ +namespace Partition +{ + +using ::Device; +using ::Partition; + +/** @brief Is this a free-space area? */ +bool isPartitionFreeSpace( 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* ); + +/** + * Iterates on all devices and return the first partition which is (already) + * mounted on @p mountPoint. + */ +Partition* findPartitionByCurrentMountPoint( const QList< Device* >& devices, const QString& mountPoint ); + +// TODO: add this distinction +// Partition* findPartitionByIntendedMountPoint( const QList< Device* >& devices, const QString& mountPoint ); + +/** + * Iterates on all devices and partitions and returns a pointer to the Partition object + * for the given path, or nullptr if a Partition for the given path cannot be found. + */ +Partition* findPartitionByPath( const QList< Device* >& devices, const QString& path ); + +/** + * Iterates on all devices and partitions and returns a list of pointers to the Partition + * objects that satisfy the conditions defined in the criterion function. + */ +QList< Partition* > findPartitions( const QList< Device* >& devices, + std::function< bool( Partition* ) > criterionFunction ); +} // namespace Partition +} // namespace CalamaresUtils + +#endif // PARTITION_PARTITIONQUERY_H diff --git a/src/libcalamares/partition/Sync.cpp b/src/libcalamares/partition/Sync.cpp new file mode 100644 index 000000000..c5e131cfa --- /dev/null +++ b/src/libcalamares/partition/Sync.cpp @@ -0,0 +1,36 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "Sync.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" + +void +CalamaresUtils::Partition::sync() +{ + auto r = CalamaresUtils::System::runCommand( { "/sbin/udevadm", "settle" }, std::chrono::seconds( 10 ) ); + + if ( r.getExitCode() != 0 ) + { + cWarning() << "Could not settle disks."; + r.explainProcess( "udevadm", std::chrono::seconds( 10 ) ); + } + + CalamaresUtils::System::runCommand( { "/bin/sync" }, std::chrono::seconds( 10 ) ); +} diff --git a/src/libcalamares/partition/Sync.h b/src/libcalamares/partition/Sync.h new file mode 100644 index 000000000..510858500 --- /dev/null +++ b/src/libcalamares/partition/Sync.h @@ -0,0 +1,46 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef PARTITION_SYNC_H +#define PARTITION_SYNC_H + +namespace CalamaresUtils +{ +namespace Partition +{ + +/** @brief Run "udevadm settle" or other disk-sync mechanism. + * + * Call this after mounting, unmount, toggling swap, or other functions + * that might cause the disk to be "busy" for other disk-modifying + * actions (in particular, KPMcore actions with the sfdisk backend + * are sensitive, and systemd tends to keep disks busy after a change + * for a while). + */ +void sync(); + +/** @brief RAII class for calling sync() */ +struct Syncer +{ + ~Syncer() { sync(); } +}; + +} // namespace Partition +} // namespace CalamaresUtils + +#endif diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 8bd696bf0..a38b28b6d 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -117,53 +117,6 @@ System::instance() } -int -System::mount( const QString& devicePath, - const QString& mountPoint, - const QString& filesystemName, - const QString& options ) -{ - if ( devicePath.isEmpty() || mountPoint.isEmpty() ) - { - if ( devicePath.isEmpty() ) - { - cWarning() << "Can't mount an empty device."; - } - if ( mountPoint.isEmpty() ) - { - cWarning() << "Can't mount on an empty mountpoint."; - } - - return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); - } - - QDir mountPointDir( mountPoint ); - if ( !mountPointDir.exists() ) - { - bool ok = mountPointDir.mkpath( mountPoint ); - if ( !ok ) - { - cWarning() << "Could not create mountpoint" << mountPoint; - return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); - } - } - - QString program( "mount" ); - QStringList args = { devicePath, mountPoint }; - - if ( !filesystemName.isEmpty() ) - { - args << "-t" << filesystemName; - } - - if ( !options.isEmpty() ) - { - args << "-o" << options; - } - - return QProcess::execute( program, args ); -} - ProcessResult System::runCommand( System::RunLocation location, const QStringList& args, diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 900634a74..a163a1208 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -138,23 +138,6 @@ public: static System* instance(); - /** - * Runs the mount utility with the specified parameters. - * @param devicePath the path of the partition to mount. - * @param mountPoint the full path of the target mount point. - * @param filesystemName the name of the filesystem (optional). - * @param options any additional options as passed to mount -o (optional). - * @returns the program's exit code, or: - * Crashed = QProcess crash - * FailedToStart = QProcess cannot start - * NoWorkingDirectory = bad arguments - */ - DLLEXPORT int mount( const QString& devicePath, - const QString& mountPoint, - const QString& filesystemName = QString(), - const QString& options = QString() ); - - /** (Typed) Boolean describing where a particular command should be run, * whether in the host (live) system or in the (chroot) target system. */ @@ -187,6 +170,16 @@ public: const QString& stdInput = QString(), std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ); + /** @brief Convenience wrapper for runCommand() + * + * Runs the given command-line @p args in the host in the current direcory + * with no input, and the given @p timeoutSec for completion. + */ + static inline ProcessResult runCommand( const QStringList& args, std::chrono::seconds timeoutSec ) + { + return runCommand( RunLocation::RunInHost, args, QString(), QString(), timeoutSec ); + } + /** @brief Convenience wrapper for runCommand(). * Runs the command in the location specified through the boolean * doChroot(), which is what you usually want for running commands diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp index c13e063bd..d16bd56f8 100644 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp +++ b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2016, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +19,7 @@ #include "PythonQtUtilsWrapper.h" +#include "partition/Mount.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include "utils/String.h" @@ -46,7 +48,7 @@ Utils::mount( const QString& device_path, const QString& filesystem_name, const QString& options ) const { - return CalamaresUtils::System::instance()->mount( device_path, mount_point, filesystem_name, options ); + return CalamaresUtils::Partition::mount( device_path, mount_point, filesystem_name, options ); } diff --git a/src/modules/fsresizer/CMakeLists.txt b/src/modules/fsresizer/CMakeLists.txt index 01f673eb8..1f4260518 100644 --- a/src/modules/fsresizer/CMakeLists.txt +++ b/src/modules/fsresizer/CMakeLists.txt @@ -8,11 +8,10 @@ set( _partition_defs "" ) if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND ) include_directories( ${KPMCORE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/modules/partition ) - if ( KPMcore_VERSION VERSION_GREATER "3.3.0") - list( APPEND _partition_defs WITH_KPMCORE331API) # kpmcore > 3.3.0 with deprecations - endif() - if ( KPMcore_VERSION VERSION_GREATER "3.90") - list( APPEND _partition_defs WITH_KPMCORE4API) # kpmcore 4 with new API + if( KPMcore_VERSION VERSION_GREATER_EQUAL "4.0" ) + list( APPEND _partition_defs WITH_KPMCORE4API ) # kpmcore 4 with new API + elseif( KPMcore_VERSION VERSION_GREATER "3.3.70" ) + message( FATAL_ERROR "KPMCore beta versions ${KPMcore_VERSION} are not supported" ) endif() # The PartitionIterator is a small class, and it's easiest -- but also a @@ -22,7 +21,6 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES ResizeFSJob.cpp - ${PROJECT_SOURCE_DIR}/src/modules/partition/core/PartitionIterator.cpp LINK_PRIVATE_LIBRARIES kpmcore calamares @@ -37,10 +35,8 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND LIBRARIES calamares_job_fsresizer # From above yamlcpp + DEFINITIONS ${_partition_defs} ) - if( TARGET fsresizertest ) - target_compile_definitions( fsresizertest PRIVATE ${_partition_defs} ) - endif() else() if ( NOT KPMcore_FOUND ) calamares_skip_module( "fsresizer (missing suitable KPMcore)" ) diff --git a/src/modules/fsresizer/ResizeFSJob.cpp b/src/modules/fsresizer/ResizeFSJob.cpp index 6b9ef9d3e..217f1315e 100644 --- a/src/modules/fsresizer/ResizeFSJob.cpp +++ b/src/modules/fsresizer/ResizeFSJob.cpp @@ -18,6 +18,14 @@ #include "ResizeFSJob.h" +#include "CalamaresVersion.h" +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "partition/PartitionIterator.h" +#include "utils/Logger.h" +#include "utils/Units.h" +#include "utils/Variant.h" + #include #include #include @@ -29,17 +37,7 @@ #include #include -#include "CalamaresVersion.h" -#include "JobQueue.h" -#include "GlobalStorage.h" - -#include "utils/Logger.h" -#include "utils/Units.h" -#include "utils/Variant.h" - -// From partition module -#include "core/PartitionIterator.h" - +using CalamaresUtils::Partition::PartitionIterator; ResizeFSJob::ResizeFSJob( QObject* parent ) : Calamares::CppJob( parent ) @@ -60,13 +58,13 @@ ResizeFSJob::prettyName() const } ResizeFSJob::PartitionMatch -ResizeFSJob::findPartition( CoreBackend* backend ) +ResizeFSJob::findPartition() { using DeviceList = QList< Device* >; -#ifdef WITH_KPMCORE331API - DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag(0) ); +#if defined( WITH_KPMCORE4API ) + DeviceList devices = m_kpmcore.backend()->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag(0) ); #else - DeviceList devices = backend->scanDevices( /* excludeReadOnly */ true ); + DeviceList devices = m_kpmcore.backend()->scanDevices( /* excludeReadOnly */ true ); #endif cDebug() << "ResizeFSJob found" << devices.count() << "devices."; @@ -172,35 +170,17 @@ ResizeFSJob::exec() tr( "Invalid configuration" ), tr( "The file-system resize job has an invalid configuration and will not run." ) ); - // Get KPMCore - auto backend_p = CoreBackendManager::self()->backend(); - if ( backend_p ) - cDebug() << "KPMCore backend @" << ( void* )backend_p << backend_p->id() << backend_p->version(); - else - { - cDebug() << "No KPMCore backend loaded yet"; - QByteArray backendName = qgetenv( "KPMCORE_BACKEND" ); - if ( !CoreBackendManager::self()->load( backendName.isEmpty() ? CoreBackendManager::defaultBackendName() : backendName ) ) - { - cWarning() << "Could not load KPMCore backend."; - return Calamares::JobResult::error( - tr( "KPMCore not Available" ), - tr( "Calamares cannot start KPMCore for the file-system resize job." ) ); - } - - backend_p = CoreBackendManager::self()->backend(); - } - if ( !backend_p ) + if ( !m_kpmcore) { cWarning() << "Could not load KPMCore backend (2)."; return Calamares::JobResult::error( tr( "KPMCore not Available" ), tr( "Calamares cannot start KPMCore for the file-system resize job." ) ); } - backend_p->initFSSupport(); // Might not be enough, see below + m_kpmcore.backend()->initFSSupport(); // Might not be enough, see below // Now get the partition and FS we want to work on - PartitionMatch m = findPartition( backend_p ); + PartitionMatch m = findPartition(); if ( !m.first || !m.second ) return Calamares::JobResult::error( tr( "Resize Failed" ), diff --git a/src/modules/fsresizer/ResizeFSJob.h b/src/modules/fsresizer/ResizeFSJob.h index 985942b99..c681fae36 100644 --- a/src/modules/fsresizer/ResizeFSJob.h +++ b/src/modules/fsresizer/ResizeFSJob.h @@ -24,6 +24,7 @@ #include +#include "partition/KPMManager.h" #include "partition/PartitionSize.h" #include "utils/PluginFactory.h" @@ -72,6 +73,7 @@ public: } private: + CalamaresUtils::Partition::KPMManager m_kpmcore; PartitionSize m_size; PartitionSize m_atleast; QString m_fsname; // Either this, or devicename, is set, not both @@ -79,8 +81,8 @@ private: bool m_required; using PartitionMatch = QPair; - /** @brief Find the configured FS using KPMCore @p backend */ - PartitionMatch findPartition( CoreBackend* backend ); + /** @brief Find the configured FS */ + PartitionMatch findPartition(); /** @brief Return a new end-sector for the given dev-part pair. */ qint64 findGrownEnd( PartitionMatch ); diff --git a/src/modules/initramfs/Tests.cpp b/src/modules/initramfs/Tests.cpp index 39d2abeaa..a9e0ce44c 100644 --- a/src/modules/initramfs/Tests.cpp +++ b/src/modules/initramfs/Tests.cpp @@ -45,6 +45,9 @@ void InitramfsTests::initTestCase() { Logger::setupLogLevel( Logger::LOGDEBUG ); + + auto* j = new Calamares::JobQueue(); + (void) new CalamaresUtils::System( true ); } static const char contents[] = "UMASK=0077\n"; @@ -55,40 +58,21 @@ void InitramfsTests::cleanup() QFile::remove( confFile ); } -void InitramfsTests::testCreateHostFile() -{ - - CalamaresUtils::System s( false ); // don't chroot - auto r = s.createTargetFile( confFile, QByteArray( contents ) ); - QVERIFY( !r.failed() ); - QVERIFY( r ); - QString path = r.path(); - QVERIFY( !path.isEmpty() ); - QCOMPARE( path, confFile ); // don't chroot, so path create relative to / - QVERIFY( QFile::exists( confFile ) ); - - QFileInfo fi( confFile ); - QVERIFY( fi.exists() ); - QCOMPARE( fi.size(), sizeof( contents )-1 ); // don't count trailing NUL - - QFile::remove( confFile ); -} - void InitramfsTests::testCreateTargetFile() { static const char short_confFile[] = "/calamares-safe-umask"; - CalamaresUtils::System s( true ); - auto r = s.createTargetFile( short_confFile, QByteArray( contents ) ); + auto* s = CalamaresUtils::System::instance(); + auto r = s->createTargetFile( short_confFile, QByteArray( contents ) ); QVERIFY( r.failed() ); QVERIFY( !r ); QString path = r.path(); QVERIFY( path.isEmpty() ); // because no rootmountpoint is set - Calamares::JobQueue j; - j.globalStorage()->insert( "rootMountPoint", "/tmp" ); + Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/tmp" ); - path = s.createTargetFile( short_confFile, QByteArray( contents ) ); + path = s->createTargetFile( short_confFile, QByteArray( contents ) ).path(); + QCOMPARE( path, QString( confFile ) ); QVERIFY( path.endsWith( short_confFile ) ); // chroot, so path create relative to QVERIFY( path.startsWith( "/tmp/" ) ); QVERIFY( QFile::exists( path ) ); diff --git a/src/modules/initramfs/Tests.h b/src/modules/initramfs/Tests.h index 01394d4fa..715c90169 100644 --- a/src/modules/initramfs/Tests.h +++ b/src/modules/initramfs/Tests.h @@ -31,8 +31,8 @@ public: private Q_SLOTS: void initTestCase(); void cleanup(); - - void testCreateHostFile(); + + // TODO: this doesn't actually test any of the functionality of this job void testCreateTargetFile(); }; diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index f9c32b39e..2ac926346 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -20,7 +20,7 @@ find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) find_package( KPMcore 3.3 ) set_package_properties( KPMcore PROPERTIES - PURPOSE "For partitioning module" + PURPOSE "For partition module" ) find_package( KF5Config CONFIG ) find_package( KF5I18n CONFIG ) @@ -51,7 +51,6 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND core/PartitionActions.cpp core/PartitionCoreModule.cpp core/PartitionInfo.cpp - core/PartitionIterator.cpp core/PartitionLayout.cpp core/PartitionModel.cpp core/PartUtils.cpp diff --git a/src/modules/partition/core/BootLoaderModel.cpp b/src/modules/partition/core/BootLoaderModel.cpp index 7f5a0427a..10b88be76 100644 --- a/src/modules/partition/core/BootLoaderModel.cpp +++ b/src/modules/partition/core/BootLoaderModel.cpp @@ -20,8 +20,8 @@ #include "core/BootLoaderModel.h" -#include "core/PartitionInfo.h" #include "core/KPMHelpers.h" +#include "core/PartitionInfo.h" #include "utils/Logger.h" @@ -44,9 +44,7 @@ BootLoaderModel::BootLoaderModel( QObject* parent ) { } -BootLoaderModel::~BootLoaderModel() -{ -} +BootLoaderModel::~BootLoaderModel() {} void BootLoaderModel::init( const QList< Device* >& devices ) @@ -67,11 +65,8 @@ BootLoaderModel::createMbrItems() { for ( auto device : m_devices ) { - QString text = tr( "Master Boot Record of %1" ) - .arg( device->name() ); - appendRow( - createBootLoaderItem( text, device->deviceNode(), false ) - ); + QString text = tr( "Master Boot Record of %1" ).arg( device->name() ); + appendRow( createBootLoaderItem( text, device->deviceNode(), false ) ); } } @@ -90,23 +85,29 @@ BootLoaderModel::update() void BootLoaderModel::updateInternal() { - QMutexLocker lock(&m_lock); + QMutexLocker lock( &m_lock ); clear(); createMbrItems(); // An empty model is possible if you don't havee permissions: don't crash though. if ( rowCount() < 1 ) + { return; + } QString partitionText; Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, "/boot" ); if ( partition ) + { partitionText = tr( "Boot Partition" ); + } else { partition = KPMHelpers::findPartitionByMountPoint( m_devices, "/" ); if ( partition ) + { partitionText = tr( "System Partition" ); + } } Q_ASSERT( rowCount() > 0 ); @@ -117,7 +118,9 @@ BootLoaderModel::updateInternal() if ( !partition ) { if ( lastIsPartition ) + { takeRow( rowCount() - 1 ); + } } else { @@ -129,15 +132,11 @@ BootLoaderModel::updateInternal() } else { - appendRow( - createBootLoaderItem( partitionText, PartitionInfo::mountPoint( partition ), true ) - ); + appendRow( createBootLoaderItem( partitionText, PartitionInfo::mountPoint( partition ), true ) ); } // Create "don't install bootloader" item - appendRow( - createBootLoaderItem( tr( "Do not install a boot loader" ), QString(), false ) - ); + appendRow( createBootLoaderItem( tr( "Do not install a boot loader" ), QString(), false ) ); } } @@ -145,13 +144,15 @@ BootLoaderModel::updateInternal() QVariant BootLoaderModel::data( const QModelIndex& index, int role ) const { - QMutexLocker lock(&m_lock); + QMutexLocker lock( &m_lock ); if ( role == Qt::DisplayRole ) { QString displayRole = QStandardItemModel::data( index, Qt::DisplayRole ).toString(); QString pathRole = QStandardItemModel::data( index, BootLoaderModel::BootLoaderPathRole ).toString(); if ( pathRole.isEmpty() ) + { return displayRole; + } return tr( "%1 (%2)" ).arg( displayRole, pathRole ); } @@ -163,14 +164,18 @@ namespace Calamares int findBootloader( const QAbstractItemModel* model, const QString& path ) { - for ( int i = 0; i < model->rowCount(); ++i) + for ( int i = 0; i < model->rowCount(); ++i ) { const auto index = model->index( i, 0, QModelIndex() ); if ( !index.isValid() ) + { continue; + } QVariant var = model->data( index, BootLoaderModel::BootLoaderPathRole ); if ( var.isValid() && var.toString() == path ) + { return i; + } } return -1; @@ -191,7 +196,7 @@ restoreSelectedBootLoader( QComboBox& combo, const QString& path ) { combo.setCurrentIndex( 0 ); } - else if ( (r = findBootloader( model, path )) >= 0 ) + else if ( ( r = findBootloader( model, path ) ) >= 0 ) { combo.setCurrentIndex( r ); } @@ -201,4 +206,4 @@ restoreSelectedBootLoader( QComboBox& combo, const QString& path ) } } -} // namespace +} // namespace Calamares diff --git a/src/modules/partition/core/BootLoaderModel.h b/src/modules/partition/core/BootLoaderModel.h index a2befad00..8daa8ca04 100644 --- a/src/modules/partition/core/BootLoaderModel.h +++ b/src/modules/partition/core/BootLoaderModel.h @@ -66,18 +66,18 @@ private: namespace Calamares { - /** @brief Returns the row number of boot-loader @p path (e.g. /dev/sda) - * - * Assuming the @p model is a BootLoaderModel, will return a row number - * in the model. Returns -1 otherwise. - */ - int findBootloader( const QAbstractItemModel* model, const QString& path ); +/** @brief Returns the row number of boot-loader @p path (e.g. /dev/sda) + * + * Assuming the @p model is a BootLoaderModel, will return a row number + * in the model. Returns -1 otherwise. + */ +int findBootloader( const QAbstractItemModel* model, const QString& path ); - /** @brief Tries to set @p path as selected item in @p combo - * - * Matches a boot-loader install path (e.g. /dev/sda) with a model - * row and sets that as the current row. - */ - void restoreSelectedBootLoader( QComboBox& combo, const QString& path ); -} // namespace +/** @brief Tries to set @p path as selected item in @p combo + * + * Matches a boot-loader install path (e.g. /dev/sda) with a model + * row and sets that as the current row. + */ +void restoreSelectedBootLoader( QComboBox& combo, const QString& path ); +} // namespace Calamares #endif /* BOOTLOADERMODEL_H */ diff --git a/src/modules/partition/core/ColorUtils.cpp b/src/modules/partition/core/ColorUtils.cpp index ffe45d443..d04c4110d 100644 --- a/src/modules/partition/core/ColorUtils.cpp +++ b/src/modules/partition/core/ColorUtils.cpp @@ -20,8 +20,9 @@ #include "core/ColorUtils.h" #include "core/KPMHelpers.h" -#include "core/PartitionIterator.h" +#include "partition/PartitionIterator.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" // KPMcore @@ -32,23 +33,25 @@ #include #include +using CalamaresUtils::Partition::isPartitionFreeSpace; +using CalamaresUtils::Partition::isPartitionNew; +using CalamaresUtils::Partition::PartitionIterator; + static const int NUM_PARTITION_COLORS = 5; static const int NUM_NEW_PARTITION_COLORS = 4; //Let's try to use the Breeze palette -static const QColor PARTITION_COLORS[ NUM_PARTITION_COLORS ] = -{ - "#2980b9", //Dark Plasma Blue - "#27ae60", //Dark Icon Green - "#c9ce3b", //Dirty Yellow - "#3daee9", //Plasma Blue - "#9b59b6", //Purple +static const QColor PARTITION_COLORS[ NUM_PARTITION_COLORS ] = { + "#2980b9", //Dark Plasma Blue + "#27ae60", //Dark Icon Green + "#c9ce3b", //Dirty Yellow + "#3daee9", //Plasma Blue + "#9b59b6", //Purple }; -static const QColor NEW_PARTITION_COLORS[ NUM_NEW_PARTITION_COLORS ] = -{ - "#c0392b", //Dark Icon Red - "#f39c1f", //Dark Icon Yellow - "#f1b7bc", //Light Salmon - "#fed999", //Light Orange +static const QColor NEW_PARTITION_COLORS[ NUM_NEW_PARTITION_COLORS ] = { + "#c0392b", //Dark Icon Red + "#f39c1f", //Dark Icon Yellow + "#f1b7bc", //Light Salmon + "#fed999", //Light Orange }; static QColor FREE_SPACE_COLOR = "#777777"; static QColor EXTENDED_COLOR = "#aaaaaa"; @@ -60,12 +63,14 @@ static QMap< QString, QColor > s_partitionColorsCache; namespace ColorUtils { -QColor freeSpaceColor() +QColor +freeSpaceColor() { return FREE_SPACE_COLOR; } -QColor unknownDisklabelColor() +QColor +unknownDisklabelColor() { return UNKNOWN_DISKLABEL_COLOR; } @@ -73,9 +78,10 @@ QColor unknownDisklabelColor() PartitionNode* _findRootForPartition( PartitionNode* partition ) { - if ( partition->isRoot() || - !partition->parent() ) + if ( partition->isRoot() || !partition->parent() ) + { return partition; + } return _findRootForPartition( partition->parent() ); } @@ -89,24 +95,31 @@ colorForPartition( Partition* partition ) return FREE_SPACE_COLOR; } - if ( KPMHelpers::isPartitionFreeSpace( partition ) ) + if ( isPartitionFreeSpace( partition ) ) + { return FREE_SPACE_COLOR; + } if ( partition->roles().has( PartitionRole::Extended ) ) + { return EXTENDED_COLOR; + } - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() ) { if ( partition->fileSystem().type() == FileSystem::Luks ) { FS::luks& luksFs = dynamic_cast< FS::luks& >( partition->fileSystem() ); - if ( !luksFs.outerUuid().isEmpty() && - s_partitionColorsCache.contains( luksFs.outerUuid() ) ) + if ( !luksFs.outerUuid().isEmpty() && s_partitionColorsCache.contains( luksFs.outerUuid() ) ) + { return s_partitionColorsCache[ luksFs.outerUuid() ]; + } } if ( s_partitionColorsCache.contains( partition->fileSystem().uuid() ) ) + { return s_partitionColorsCache[ partition->fileSystem().uuid() ]; + } } // No partition-specific color needed, pick one from our list, but skip @@ -117,27 +130,30 @@ colorForPartition( Partition* partition ) Q_ASSERT( table ); int colorIdx = 0; int newColorIdx = 0; - for ( PartitionIterator it = PartitionIterator::begin( table ); - it != PartitionIterator::end( table ); - ++it ) + for ( PartitionIterator it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it ) { Partition* child = *it; if ( child == partition ) - break; - if ( !KPMHelpers::isPartitionFreeSpace( child ) && - !child->hasChildren() ) { - if ( KPMHelpers::isPartitionNew( child ) ) + break; + } + if ( !isPartitionFreeSpace( child ) && !child->hasChildren() ) + { + if ( isPartitionNew( child ) ) + { ++newColorIdx; + } ++colorIdx; } } - if ( KPMHelpers::isPartitionNew( partition ) ) + if ( isPartitionNew( partition ) ) + { return NEW_PARTITION_COLORS[ newColorIdx % NUM_NEW_PARTITION_COLORS ]; + } - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() ) { if ( partition->fileSystem().type() == FileSystem::Luks ) { @@ -163,17 +179,17 @@ colorForPartitionInFreeSpace( Partition* partition ) PartitionTable* table = dynamic_cast< PartitionTable* >( parent ); Q_ASSERT( table ); int newColorIdx = 0; - for ( PartitionIterator it = PartitionIterator::begin( table ); - it != PartitionIterator::end( table ); - ++it ) + for ( PartitionIterator it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it ) { Partition* child = *it; if ( child == partition ) + { break; - if ( !KPMHelpers::isPartitionFreeSpace( child ) && - !child->hasChildren() && - KPMHelpers::isPartitionNew( child ) ) + } + if ( !isPartitionFreeSpace( child ) && !child->hasChildren() && isPartitionNew( child ) ) + { ++newColorIdx; + } } return NEW_PARTITION_COLORS[ newColorIdx % NUM_NEW_PARTITION_COLORS ]; } @@ -185,4 +201,4 @@ invalidateCache() s_partitionColorsCache.clear(); } -} // namespace +} // namespace ColorUtils diff --git a/src/modules/partition/core/ColorUtils.h b/src/modules/partition/core/ColorUtils.h index 33efc4b7e..3c65b75b2 100644 --- a/src/modules/partition/core/ColorUtils.h +++ b/src/modules/partition/core/ColorUtils.h @@ -53,6 +53,6 @@ QColor colorForPartitionInFreeSpace( Partition* freeSpacePartition ); */ void invalidateCache(); -} +} // namespace ColorUtils #endif /* COLORUTILS_H */ diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp index 680d30dd6..944940d9a 100644 --- a/src/modules/partition/core/DeviceList.cpp +++ b/src/modules/partition/core/DeviceList.cpp @@ -20,23 +20,24 @@ #include "DeviceList.h" #include "PartitionCoreModule.h" - #include "core/DeviceModel.h" #include "core/KPMHelpers.h" -#include "core/PartitionIterator.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "partition/PartitionIterator.h" +#include "utils/Logger.h" #include #include #include #include -#include -#include -#include - #include #include +using CalamaresUtils::Partition::PartitionIterator; + namespace PartUtils { @@ -49,7 +50,9 @@ hasRootPartition( Device* device ) { for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) if ( ( *it )->mountPoint() == "/" ) + { return true; + } return false; } @@ -68,17 +71,22 @@ isIso9660( const Device* device ) { const QString path = device->deviceNode(); if ( path.isEmpty() ) + { return false; + } if ( blkIdCheckIso9660( path ) ) + { return true; + } - if ( device->partitionTable() && - !device->partitionTable()->children().isEmpty() ) + if ( device->partitionTable() && !device->partitionTable()->children().isEmpty() ) { for ( const Partition* partition : device->partitionTable()->children() ) { if ( blkIdCheckIso9660( partition->partitionPath() ) ) + { return true; + } } } return false; @@ -86,7 +94,7 @@ isIso9660( const Device* device ) static inline QDebug& -operator <<( QDebug& s, QList< Device* >::iterator& it ) +operator<<( QDebug& s, QList< Device* >::iterator& it ) { s << ( ( *it ) ? ( *it )->deviceNode() : QString( "" ) ); return s; @@ -95,7 +103,7 @@ operator <<( QDebug& s, QList< Device* >::iterator& it ) using DeviceList = QList< Device* >; static inline DeviceList::iterator -erase(DeviceList& l, DeviceList::iterator& it) +erase( DeviceList& l, DeviceList::iterator& it ) { Device* p = *it; auto r = l.erase( it ); @@ -103,13 +111,14 @@ erase(DeviceList& l, DeviceList::iterator& it) return r; } -QList< Device* > getDevices( DeviceType which, qint64 minimumSize ) +QList< Device* > +getDevices( DeviceType which, qint64 minimumSize ) { - bool writableOnly = (which == DeviceType::WritableOnly); + bool writableOnly = ( which == DeviceType::WritableOnly ); CoreBackend* backend = CoreBackendManager::self()->backend(); -#ifdef WITH_KPMCORE331API - DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag(0) ); +#if defined( WITH_KPMCORE4API ) + DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) ); #else DeviceList devices = backend->scanDevices( /* excludeReadOnly */ true ); #endif @@ -127,14 +136,12 @@ QList< Device* > getDevices( DeviceType which, qint64 minimumSize ) if ( !( *it ) ) { cDebug() << Logger::SubEntry << "Skipping nullptr device"; - it = erase( devices, it); + it = erase( devices, it ); } - else if ( ( *it )->deviceNode().startsWith( "/dev/zram" ) - ) + else if ( ( *it )->deviceNode().startsWith( "/dev/zram" ) ) { cDebug() << Logger::SubEntry << "Removing zram" << it; it = erase( devices, it ); - } else if ( writableOnly && hasRootPartition( *it ) ) { @@ -146,13 +153,15 @@ QList< Device* > getDevices( DeviceType which, qint64 minimumSize ) cDebug() << Logger::SubEntry << "Removing device with iso9660 filesystem (probably a CD) on it" << it; it = erase( devices, it ); } - else if ( (minimumSize >= 0) && !( (*it)->capacity() > minimumSize ) ) + else if ( ( minimumSize >= 0 ) && !( ( *it )->capacity() > minimumSize ) ) { cDebug() << Logger::SubEntry << "Removing too-small" << it; it = erase( devices, it ); } else + { ++it; + } #endif return devices; diff --git a/src/modules/partition/core/DeviceList.h b/src/modules/partition/core/DeviceList.h index 3754f58e6..6823d6951 100644 --- a/src/modules/partition/core/DeviceList.h +++ b/src/modules/partition/core/DeviceList.h @@ -28,7 +28,11 @@ class Device; namespace PartUtils { -enum class DeviceType { All, WritableOnly }; +enum class DeviceType +{ + All, + WritableOnly +}; /** * @brief Gets a list of storage devices. @@ -43,6 +47,6 @@ enum class DeviceType { All, WritableOnly }; */ QList< Device* > getDevices( DeviceType which = DeviceType::All, qint64 minimumSize = -1 ); -} +} // namespace PartUtils -#endif // DEVICELIST_H +#endif // DEVICELIST_H diff --git a/src/modules/partition/core/DeviceModel.cpp b/src/modules/partition/core/DeviceModel.cpp index c76c39090..f881d265b 100644 --- a/src/modules/partition/core/DeviceModel.cpp +++ b/src/modules/partition/core/DeviceModel.cpp @@ -30,8 +30,8 @@ // KF5 #include -#include #include +#include // STL #include @@ -39,8 +39,7 @@ static void sortDevices( DeviceModel::DeviceList& l ) { - std::sort( l.begin(), l.end(), []( const Device* dev1, const Device* dev2 ) - { + std::sort( l.begin(), l.end(), []( const Device* dev1, const Device* dev2 ) { return dev1->deviceNode() < dev2->deviceNode(); } ); } @@ -50,9 +49,7 @@ DeviceModel::DeviceModel( QObject* parent ) { } -DeviceModel::~DeviceModel() -{ -} +DeviceModel::~DeviceModel() {} void DeviceModel::init( const DeviceList& devices ) @@ -74,7 +71,9 @@ DeviceModel::data( const QModelIndex& index, int role ) const { int row = index.row(); if ( row < 0 || row >= m_devices.count() ) + { return QVariant(); + } Device* device = m_devices.at( row ); @@ -83,16 +82,18 @@ DeviceModel::data( const QModelIndex& index, int role ) const case Qt::DisplayRole: case Qt::ToolTipRole: if ( device->name().isEmpty() ) + { return device->deviceNode(); + } else { if ( device->logicalSize() >= 0 && device->totalLogical() >= 0 ) { //: device[name] - size[number] (device-node[name]) return tr( "%1 - %2 (%3)" ) - .arg( device->name() ) - .arg( KFormat().formatByteSize( device->capacity() ) ) - .arg( device->deviceNode() ); + .arg( device->name() ) + .arg( KFormat().formatByteSize( device->capacity() ) ) + .arg( device->deviceNode() ); } else { @@ -100,16 +101,14 @@ DeviceModel::data( const QModelIndex& index, int role ) const // always has 1B capacity), so don't show it for a while. // //: device[name] - (device-node[name]) - return tr( "%1 - (%2)" ) - .arg( device->name() ) - .arg( device->deviceNode() ); + return tr( "%1 - (%2)" ).arg( device->name() ).arg( device->deviceNode() ); } - } + } case Qt::DecorationRole: - return CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionDisk, - CalamaresUtils::Original, - QSize( CalamaresUtils::defaultIconSize().width() * 3, - CalamaresUtils::defaultIconSize().height() * 3 ) ); + return CalamaresUtils::defaultPixmap( + CalamaresUtils::PartitionDisk, + CalamaresUtils::Original, + QSize( CalamaresUtils::defaultIconSize().width() * 3, CalamaresUtils::defaultIconSize().height() * 3 ) ); default: return QVariant(); } @@ -121,7 +120,9 @@ DeviceModel::deviceForIndex( const QModelIndex& index ) const { int row = index.row(); if ( row < 0 || row >= m_devices.count() ) + { return nullptr; + } return m_devices.at( row ); } @@ -134,7 +135,9 @@ DeviceModel::swapDevice( Device* oldDevice, Device* newDevice ) int indexOfOldDevice = m_devices.indexOf( oldDevice ); if ( indexOfOldDevice < 0 ) + { return; + } m_devices[ indexOfOldDevice ] = newDevice; @@ -142,7 +145,7 @@ DeviceModel::swapDevice( Device* oldDevice, Device* newDevice ) } void -DeviceModel::addDevice( Device *device ) +DeviceModel::addDevice( Device* device ) { beginResetModel(); m_devices << device; @@ -151,7 +154,7 @@ DeviceModel::addDevice( Device *device ) } void -DeviceModel::removeDevice( Device *device ) +DeviceModel::removeDevice( Device* device ) { beginResetModel(); m_devices.removeAll( device ); diff --git a/src/modules/partition/core/DeviceModel.h b/src/modules/partition/core/DeviceModel.h index f3e158bbf..29d1598ad 100644 --- a/src/modules/partition/core/DeviceModel.h +++ b/src/modules/partition/core/DeviceModel.h @@ -20,8 +20,8 @@ #define DEVICEMODEL_H #include -#include #include +#include class Device; class PartitionModel; diff --git a/src/modules/partition/core/KPMHelpers.cpp b/src/modules/partition/core/KPMHelpers.cpp index 0265a17e5..730d1d9af 100644 --- a/src/modules/partition/core/KPMHelpers.cpp +++ b/src/modules/partition/core/KPMHelpers.cpp @@ -21,94 +21,35 @@ #include "core/KPMHelpers.h" #include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" + +#include "partition/PartitionIterator.h" +#include "utils/Logger.h" // KPMcore +#include #include #include #include -#include #include -#include "utils/Logger.h" - -#include - +using CalamaresUtils::Partition::PartitionIterator; namespace KPMHelpers { -static bool s_KPMcoreInited = false; - -bool -initKPMcore() -{ - if ( s_KPMcoreInited ) - return true; - - QByteArray backendName = qgetenv( "KPMCORE_BACKEND" ); - if ( !CoreBackendManager::self()->load( backendName.isEmpty() ? CoreBackendManager::defaultBackendName() : backendName ) ) - { - cWarning() << "Failed to load backend plugin" << backendName; - return false; - } - s_KPMcoreInited = true; - return true; -} - - -bool -isPartitionFreeSpace( Partition* partition ) -{ - return partition->roles().has( PartitionRole::Unallocated ); -} - - -bool -isPartitionNew( Partition* partition ) -{ - return partition->state() == KPM_PARTITION_STATE(New); -} - - Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ) { for ( auto device : devices ) for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) if ( PartitionInfo::mountPoint( *it ) == mountPoint ) + { return *it; + } return nullptr; } -Partition* -findPartitionByPath( const QList< Device* >& devices, const QString& path ) -{ - if ( path.simplified().isEmpty() ) - return nullptr; - - for ( auto device : devices ) - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - if ( ( *it )->partitionPath() == path.simplified() ) - return *it; - return nullptr; -} - - -QList< Partition* > -findPartitions( const QList< Device* >& devices, - std::function< bool ( Partition* ) > criterionFunction ) -{ - 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; -} - - Partition* createNewPartition( PartitionNode* parent, const Device& device, @@ -118,21 +59,19 @@ createNewPartition( PartitionNode* parent, qint64 lastSector, PartitionTable::Flags flags ) { - FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector - ,device.logicalSize() - ); - return new Partition( - parent, - device, - role, - fs, fs->firstSector(), fs->lastSector(), - QString() /* path */, - KPM_PARTITION_FLAG(None) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - flags /* activeFlags */, - KPM_PARTITION_STATE(New) - ); + FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector, device.logicalSize() ); + return new Partition( parent, + device, + role, + fs, + fs->firstSector(), + fs->lastSector(), + QString() /* path */, + KPM_PARTITION_FLAG( None ) /* availableFlags */, + QString() /* mountPoint */, + false /* mounted */, + flags /* activeFlags */, + KPM_PARTITION_STATE( New ) ); } @@ -148,14 +87,12 @@ createNewEncryptedPartition( PartitionNode* parent, { PartitionRole::Roles newRoles = role.roles(); if ( !role.has( PartitionRole::Luks ) ) + { newRoles |= PartitionRole::Luks; + } FS::luks* fs = dynamic_cast< FS::luks* >( - FileSystemFactory::create( FileSystem::Luks, - firstSector, - lastSector - ,device.logicalSize() - ) ); + FileSystemFactory::create( FileSystem::Luks, firstSector, lastSector, device.logicalSize() ) ); if ( !fs ) { cError() << "cannot create LUKS filesystem. Giving up."; @@ -167,13 +104,15 @@ createNewEncryptedPartition( PartitionNode* parent, Partition* p = new Partition( parent, device, PartitionRole( newRoles ), - fs, fs->firstSector(), fs->lastSector(), + fs, + fs->firstSector(), + fs->lastSector(), QString() /* path */, - KPM_PARTITION_FLAG(None) /* availableFlags */, + KPM_PARTITION_FLAG( None ) /* availableFlags */, QString() /* mountPoint */, false /* mounted */, flags /* activeFlags */, - KPM_PARTITION_STATE(New) ); + KPM_PARTITION_STATE( New ) ); return p; } @@ -182,11 +121,7 @@ Partition* clonePartition( Device* device, Partition* partition ) { FileSystem* fs = FileSystemFactory::create( - partition->fileSystem().type(), - partition->firstSector(), - partition->lastSector() - ,device->logicalSize() - ); + partition->fileSystem().type(), partition->firstSector(), partition->lastSector(), device->logicalSize() ); return new Partition( partition->parent(), *device, partition->roles(), @@ -197,48 +132,4 @@ clonePartition( Device* device, Partition* partition ) partition->activeFlags() ); } - -QString -prettyNameForFileSystemType( FileSystem::Type t ) -{ - switch ( t ) - { - case FileSystem::Unknown: - return QObject::tr( "unknown" ); - case FileSystem::Extended: - return QObject::tr( "extended" ); - case FileSystem::Unformatted: - return QObject::tr( "unformatted" ); - case FileSystem::LinuxSwap: - return QObject::tr( "swap" ); - case FileSystem::Fat16: - case FileSystem::Fat32: - case FileSystem::Ntfs: - case FileSystem::Xfs: - case FileSystem::Jfs: - case FileSystem::Hfs: - case FileSystem::Ufs: - case FileSystem::Hpfs: - case FileSystem::Luks: - case FileSystem::Ocfs2: - case FileSystem::Zfs: - case FileSystem::Nilfs2: - return FileSystem::nameForType( t ).toUpper(); - case FileSystem::ReiserFS: - return "ReiserFS"; - case FileSystem::Reiser4: - return "Reiser4"; - case FileSystem::HfsPlus: - return "HFS+"; - case FileSystem::Btrfs: - return "Btrfs"; - case FileSystem::Exfat: - return "exFAT"; - case FileSystem::Lvm2_PV: - return "LVM PV"; - default: - return FileSystem::nameForType( t ); - } -} - -} // namespace +} // namespace KPMHelpers diff --git a/src/modules/partition/core/KPMHelpers.h b/src/modules/partition/core/KPMHelpers.h index bb510cafb..326993362 100644 --- a/src/modules/partition/core/KPMHelpers.h +++ b/src/modules/partition/core/KPMHelpers.h @@ -34,13 +34,13 @@ class Partition; class PartitionNode; class PartitionRole; -#ifdef WITH_KPMCORE331API -#define KPM_PARTITION_FLAG(x) PartitionTable::Flag::x -#define KPM_PARTITION_STATE(x) Partition::State::x +#if defined( WITH_KPMCORE4API ) +#define KPM_PARTITION_FLAG( x ) PartitionTable::Flag::x +#define KPM_PARTITION_STATE( x ) Partition::State::x #define KPM_PARTITION_FLAG_ESP PartitionTable::Flag::Boot #else -#define KPM_PARTITION_FLAG(x) PartitionTable::Flag##x -#define KPM_PARTITION_STATE(x) Partition::State##x +#define KPM_PARTITION_FLAG( x ) PartitionTable::Flag##x +#define KPM_PARTITION_STATE( x ) Partition::State##x #define KPM_PARTITION_FLAG_ESP PartitionTable::FlagEsp #endif @@ -50,46 +50,12 @@ class PartitionRole; namespace KPMHelpers { -/** - * Thin wrapper on top of CoreBackendManager. Hides things like initializing the - * Config instance or instantiating the backend. - * - * Initialize PartitionManager Config object and load a PartitionManager - * backend. It loads the "libparted" plugin by default, but this can be - * overloaded by settings the environment variable KPMCORE_BACKEND. Setting it to - * "dummy" will load the dummy plugin instead. - * - * @return true if initialization was successful. - */ -bool initKPMcore(); - -bool isPartitionFreeSpace( Partition* ); - -/** - * Returns true if the partition is planned to be created by the installer as - * opposed to already existing on the disk. - */ -bool isPartitionNew( Partition* ); - /** * Iterates on all devices and return the first partition which is associated * with mountPoint. This uses PartitionInfo::mountPoint(), not Partition::mountPoint() */ Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ); -/** - * Iterates on all devices and partitions and returns a pointer to the Partition object - * for the given path, or nullptr if a Partition for the given path cannot be found. - */ -Partition* findPartitionByPath( const QList< Device* >& devices, const QString& path ); - -/** - * Iterates on all devices and partitions and returns a list of pointers to the Partition - * objects that satisfy the conditions defined in the criterion function. - */ -QList< Partition* > findPartitions( const QList< Device* >& devices, - std::function< bool ( Partition* ) > criterionFunction ); - /** * Helper function to create a new Partition object (does not create anything * on the disk) associated with a FileSystem. @@ -113,32 +79,6 @@ Partition* createNewEncryptedPartition( PartitionNode* parent, Partition* clonePartition( Device* device, Partition* partition ); -QString prettyNameForFileSystemType( FileSystem::Type t ); - -static inline QString -untranslatedFS( FileSystem& fs ) -{ - return fs.name( { QStringLiteral( "C" ) } ); -} - -static inline QString -untranslatedFS( FileSystem* fs ) -{ - return fs ? untranslatedFS( *fs ) : QString(); -} - -static inline QString -userVisibleFS( FileSystem& fs ) -{ - return fs.name(); -} - -static inline QString -userVisibleFS( FileSystem* fs ) -{ - return fs ? userVisibleFS( *fs ) : QString(); -} - -} +} // namespace KPMHelpers #endif /* KPMHELPERS_H */ diff --git a/src/modules/partition/core/OsproberEntry.h b/src/modules/partition/core/OsproberEntry.h index e8c7895f0..1e1fd0eca 100644 --- a/src/modules/partition/core/OsproberEntry.h +++ b/src/modules/partition/core/OsproberEntry.h @@ -32,7 +32,7 @@ struct FstabEntry int pass; /// Does this entry make sense and is it complete? - bool isValid() const; // implemented in Partutils.cpp + bool isValid() const; // implemented in Partutils.cpp /** @brief Create an entry from a live of /etc/fstab * @@ -41,7 +41,7 @@ struct FstabEntry * If the string isn't valid (e.g. comment-line, or broken * fstab entry) then the entry that is returned is invalid. */ - static FstabEntry fromEtcFstab( const QString& ); // implemented in Partutils.cpp + static FstabEntry fromEtcFstab( const QString& ); // implemented in Partutils.cpp }; typedef QList< FstabEntry > FstabEntryList; @@ -59,4 +59,4 @@ struct OsproberEntry typedef QList< OsproberEntry > OsproberEntryList; -#endif // OSPROBERENTRY_H +#endif // OSPROBERENTRY_H diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 94630b472..4cc59d518 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -25,21 +25,26 @@ #include "core/DeviceModel.h" #include "core/KPMHelpers.h" #include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "partition/Mount.h" +#include "partition/PartitionIterator.h" +#include "partition/PartitionQuery.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" #include #include #include #include -#include -#include -#include -#include - #include #include +using CalamaresUtils::Partition::isPartitionFreeSpace; +using CalamaresUtils::Partition::isPartitionNew; + namespace PartUtils { @@ -47,17 +52,25 @@ 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; + s << (void*)candidate; return p; } @@ -106,9 +119,9 @@ canBeReplaced( Partition* candidate ) Logger::CDebug deb; deb << Logger::SubEntry << "NO, insufficient storage"; deb << Logger::Continuation << "Required storage B:" << requiredStorageB - << QString( "(%1GiB)" ).arg( requiredStorageGiB ); + << QString( "(%1GiB)" ).arg( requiredStorageGiB ); deb << Logger::Continuation << "Available storage B:" << availableStorageB - << QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) ); + << QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) ); return false; } } @@ -124,15 +137,14 @@ canBeResized( Partition* candidate ) } cDebug() << "Checking if" << convenienceName( candidate ) << "can be resized."; - if ( !candidate->fileSystem().supportGrow() || - !candidate->fileSystem().supportShrink() ) + if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) { cDebug() << Logger::SubEntry << "NO, filesystem" << candidate->fileSystem().name() - << "does not support resize."; + << "does not support resize."; return false; } - if ( KPMHelpers::isPartitionFreeSpace( candidate ) ) + if ( isPartitionFreeSpace( candidate ) ) { cDebug() << Logger::SubEntry << "NO, partition is free space"; return false; @@ -155,8 +167,8 @@ canBeResized( Partition* candidate ) if ( table->numPrimaries() >= table->maxPrimaries() ) { - cDebug() << Logger::SubEntry << "NO, partition table already has" - << table->maxPrimaries() << "primary partitions."; + cDebug() << Logger::SubEntry << "NO, partition table already has" << table->maxPrimaries() + << "primary partitions."; return false; } } @@ -184,11 +196,11 @@ canBeResized( Partition* candidate ) Logger::CDebug deb; deb << Logger::SubEntry << "NO, insufficient storage"; deb << Logger::Continuation << "Required storage B:" << advisedStorageB - << QString( "(%1GiB)" ).arg( advisedStorageGiB ); + << QString( "(%1GiB)" ).arg( advisedStorageGiB ); deb << Logger::Continuation << "Available storage B:" << availableStorageB - << QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) ) - << "for" << convenienceName( candidate ) << "length:" << candidate->length() - << "sectorsUsed:" << candidate->sectorsUsed() << "fsType:" << candidate->fileSystem().name(); + << QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) ) << "for" + << convenienceName( candidate ) << "length:" << candidate->length() + << "sectorsUsed:" << candidate->sectorsUsed() << "fsType:" << candidate->fileSystem().name(); return false; } } @@ -205,7 +217,7 @@ canBeResized( PartitionCoreModule* core, const QString& partitionPath ) for ( int i = 0; i < dm->rowCount(); ++i ) { Device* dev = dm->deviceForIndex( dm->index( i ) ); - Partition* candidate = KPMHelpers::findPartitionByPath( { dev }, partitionWithOs ); + Partition* candidate = CalamaresUtils::Partition::findPartitionByPath( { dev }, partitionWithOs ); if ( candidate ) { return canBeResized( candidate ); @@ -222,66 +234,69 @@ canBeResized( PartitionCoreModule* core, const QString& partitionPath ) static FstabEntryList lookForFstabEntries( const QString& partitionPath ) { - QStringList mountOptions{ "ro" }; + QStringList mountOptions { "ro" }; - auto r = CalamaresUtils::System::runCommand( - CalamaresUtils::System::RunLocation::RunInHost, - { "blkid", "-s", "TYPE", "-o", "value", partitionPath } - ); + auto r = CalamaresUtils::System::runCommand( CalamaresUtils::System::RunLocation::RunInHost, + { "blkid", "-s", "TYPE", "-o", "value", partitionPath } ); if ( r.getExitCode() ) + { cWarning() << "blkid on" << partitionPath << "failed."; + } else { QString fstype = r.getOutput().trimmed(); if ( ( fstype == "ext3" ) || ( fstype == "ext4" ) ) + { mountOptions.append( "noload" ); + } } - cDebug() << "Checking device" << partitionPath - << "for fstab (fs=" << r.getOutput() << ')'; + cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; FstabEntryList fstabEntries; - QTemporaryDir mountsDir; - mountsDir.setAutoRemove( false ); - int exit = QProcess::execute( "mount", { "-o", mountOptions.join(','), partitionPath, mountsDir.path() } ); - if ( !exit ) // if all is well + CalamaresUtils::Partition::TemporaryMount mount( partitionPath, QString(), mountOptions.join( ',' ) ); + if ( mount.isValid() ) { - QFile fstabFile( mountsDir.path() + "/etc/fstab" ); + QFile fstabFile( mount.path() + "/etc/fstab" ); cDebug() << Logger::SubEntry << "reading" << fstabFile.fileName(); if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { - const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ) - .split( '\n' ); + const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ).split( '\n' ); for ( const QString& rawLine : fstabLines ) + { fstabEntries.append( FstabEntry::fromEtcFstab( rawLine ) ); + } fstabFile.close(); cDebug() << Logger::SubEntry << "got" << fstabEntries.count() << "lines."; - std::remove_if( fstabEntries.begin(), fstabEntries.end(), [](const FstabEntry& x) { return !x.isValid(); } ); + std::remove_if( + fstabEntries.begin(), fstabEntries.end(), []( const FstabEntry& x ) { return !x.isValid(); } ); cDebug() << Logger::SubEntry << "got" << fstabEntries.count() << "fstab entries."; } else + { cWarning() << "Could not read fstab from mounted fs"; - - if ( QProcess::execute( "umount", { "-R", mountsDir.path() } ) ) - cWarning() << "Could not unmount" << mountsDir.path(); + } } else + { cWarning() << "Could not mount existing fs"; + } return fstabEntries; } static QString -findPartitionPathForMountPoint( const FstabEntryList& fstab, - const QString& mountPoint ) +findPartitionPathForMountPoint( const FstabEntryList& fstab, const QString& mountPoint ) { if ( fstab.isEmpty() ) + { return QString(); + } for ( const FstabEntry& entry : fstab ) { @@ -290,7 +305,7 @@ findPartitionPathForMountPoint( const FstabEntryList& fstab, QProcess readlink; QString partPath; - if ( entry.partitionNode.startsWith( "/dev" ) ) // plain dev node + if ( entry.partitionNode.startsWith( "/dev" ) ) // plain dev node { partPath = entry.partitionNode; } @@ -325,17 +340,22 @@ findPartitionPathForMountPoint( const FstabEntryList& fstab, // At this point we either have /dev/sda1, or /dev/disk/by-something/... - if ( partPath.startsWith( "/dev/disk/by-" ) ) // we got a fancy node + if ( partPath.startsWith( "/dev/disk/by-" ) ) // we got a fancy node { - readlink.start( "readlink", { "-en", partPath }); + readlink.start( "readlink", { "-en", partPath } ); if ( !readlink.waitForStarted( 1000 ) ) + { return QString(); + } if ( !readlink.waitForFinished( 1000 ) ) + { return QString(); + } if ( readlink.exitCode() != 0 || readlink.exitStatus() != QProcess::NormalExit ) + { return QString(); - partPath = QString::fromLocal8Bit( - readlink.readAllStandardOutput() ).trimmed(); + } + partPath = QString::fromLocal8Bit( readlink.readAllStandardOutput() ).trimmed(); } return partPath; @@ -364,9 +384,7 @@ runOsprober( PartitionCoreModule* core ) } else { - osproberOutput.append( - QString::fromLocal8Bit( - osprober.readAllStandardOutput() ).trimmed() ); + osproberOutput.append( QString::fromLocal8Bit( osprober.readAllStandardOutput() ).trimmed() ); } QStringList osproberCleanLines; @@ -379,32 +397,37 @@ runOsprober( PartitionCoreModule* core ) QStringList lineColumns = line.split( ':' ); QString prettyName; if ( !lineColumns.value( 1 ).simplified().isEmpty() ) + { prettyName = lineColumns.value( 1 ).simplified(); + } else if ( !lineColumns.value( 2 ).simplified().isEmpty() ) + { prettyName = lineColumns.value( 2 ).simplified(); + } QString path = lineColumns.value( 0 ).simplified(); - if ( !path.startsWith( "/dev/" ) ) //basic sanity check + if ( !path.startsWith( "/dev/" ) ) //basic sanity check + { continue; + } FstabEntryList fstabEntries = lookForFstabEntries( path ); QString homePath = findPartitionPathForMountPoint( fstabEntries, "/home" ); - osproberEntries.append( { prettyName, - path, - QString(), - canBeResized( core, path ), - lineColumns, - fstabEntries, - homePath } ); + osproberEntries.append( + { prettyName, path, QString(), canBeResized( core, path ), lineColumns, fstabEntries, homePath } ); osproberCleanLines.append( line ); } } if ( osproberCleanLines.count() > 0 ) + { cDebug() << "os-prober lines after cleanup:" << Logger::DebugList( osproberCleanLines ); + } else + { cDebug() << "os-prober gave no output."; + } Calamares::JobQueue::instance()->globalStorage()->insert( "osproberLines", osproberCleanLines ); @@ -427,24 +450,28 @@ isEfiBootable( const Partition* candidate ) /* If bit 17 is set, old-style Esp flag, it's OK */ if ( flags.testFlag( KPM_PARTITION_FLAG_ESP ) ) + { return true; + } /* Otherwise, if it's a GPT table, Boot (bit 0) is the same as Esp */ const PartitionNode* root = candidate; while ( root && !root->isRoot() ) { root = root->parent(); - cDebug() << Logger::SubEntry << "moved towards root" << (void *)root; + cDebug() << Logger::SubEntry << "moved towards root" << (void*)root; } // Strange case: no root found, no partition table node? if ( !root ) + { return false; + } - const PartitionTable* table = dynamic_cast( root ); - cDebug() << Logger::SubEntry << "partition table" << (void *)table << "type" << ( table ? table->type() : PartitionTable::TableType::unknownTableType ); - return table && ( table->type() == PartitionTable::TableType::gpt ) && - flags.testFlag( KPM_PARTITION_FLAG(Boot) ); + const PartitionTable* table = dynamic_cast< const PartitionTable* >( root ); + cDebug() << Logger::SubEntry << "partition table" << (void*)table << "type" + << ( table ? table->type() : PartitionTable::TableType::unknownTableType ); + return table && ( table->type() == PartitionTable::TableType::gpt ) && flags.testFlag( KPM_PARTITION_FLAG( Boot ) ); } QString @@ -452,14 +479,18 @@ findFS( QString fsName, FileSystem::Type* fsType ) { QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization if ( fsName.isEmpty() ) + { fsName = QStringLiteral( "ext4" ); + } FileSystem::Type tmpType = FileSystem::typeForName( fsName, fsLanguage ); if ( tmpType != FileSystem::Unknown ) { cDebug() << "Found filesystem" << fsName; if ( fsType ) + { *fsType = tmpType; + } return fsName; } @@ -472,7 +503,9 @@ findFS( QString fsName, FileSystem::Type* fsType ) QString fsRealName = FileSystem::nameForType( t, fsLanguage ); cDebug() << "Filesystem name" << fsName << "translated to" << fsRealName; if ( fsType ) + { *fsType = t; + } return fsRealName; } } @@ -480,8 +513,10 @@ findFS( QString fsName, FileSystem::Type* fsType ) cDebug() << "Filesystem" << fsName << "not found, using ext4"; fsName = QStringLiteral( "ext4" ); // fsType can be used to check whether fsName was a valid filesystem. - if (fsType) + if ( fsType ) + { *fsType = FileSystem::Unknown; + } #ifdef DEBUG_FILESYSTEMS // This bit is for distro's debugging their settings, and shows // all the strings that KPMCore is matching against for FS type. @@ -491,13 +526,15 @@ findFS( QString fsName, FileSystem::Type* fsType ) const auto fstypes = FileSystem::types(); d << "Available types (" << fstypes.count() << ')'; for ( FileSystem::Type t : fstypes ) - d << TR( static_cast( t ), FileSystem::nameForType( t, fsLanguage ) ); + { + d << TR( static_cast< int >( t ), FileSystem::nameForType( t, fsLanguage ) ); + } } #endif return fsName; } -} // nmamespace PartUtils +} // namespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ @@ -512,17 +549,18 @@ FstabEntry::fromEtcFstab( const QString& rawLine ) { QString line = rawLine.simplified(); if ( line.startsWith( '#' ) ) - return FstabEntry{ QString(), QString(), QString(), QString(), 0, 0 }; + return FstabEntry { QString(), QString(), QString(), QString(), 0, 0 }; QStringList splitLine = line.split( ' ' ); if ( splitLine.length() != 6 ) - return FstabEntry{ QString(), QString(), QString(), QString(), 0, 0 }; + return FstabEntry { QString(), QString(), QString(), QString(), 0, 0 }; - return FstabEntry{ splitLine.at( 0 ), // path, or UUID, or LABEL, etc. - splitLine.at( 1 ), // mount point - splitLine.at( 2 ), // fs type - splitLine.at( 3 ), // options - splitLine.at( 4 ).toInt(), //dump - splitLine.at( 5 ).toInt() //pass - }; - } + return FstabEntry { + splitLine.at( 0 ), // path, or UUID, or LABEL, etc. + splitLine.at( 1 ), // mount point + splitLine.at( 2 ), // fs type + splitLine.at( 3 ), // options + splitLine.at( 4 ).toInt(), //dump + splitLine.at( 5 ).toInt() //pass + }; +} diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 1b4ee0b71..0db49d043 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -22,8 +22,8 @@ #define PARTUTILS_H #include "OsproberEntry.h" -#include "utils/Units.h" #include "utils/NamedSuffix.h" +#include "utils/Units.h" // KPMcore #include @@ -99,6 +99,6 @@ bool isEfiBootable( const Partition* candidate ); */ QString findFS( QString fsName, FileSystem::Type* fsType ); -} +} // namespace PartUtils -#endif // PARTUTILS_H +#endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index f0d5acdd9..5e785c9d1 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -21,13 +21,13 @@ #include "PartitionActions.h" #include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" -#include "core/PartitionCoreModule.h" #include "core/PartUtils.h" +#include "core/PartitionCoreModule.h" +#include "core/PartitionInfo.h" #include "utils/CalamaresUtilsSystem.h" -#include "utils/Units.h" #include "utils/NamedEnum.h" +#include "utils/Units.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -47,7 +47,9 @@ qint64 swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) { if ( ( swap != Choices::SmallSwap ) && ( swap != Choices::FullSwap ) ) + { return 0; + } // See partition.conf for explanation qint64 suggestedSwapSizeB = 0; @@ -59,15 +61,23 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) // Ramp up quickly to 8GiB, then follow memory size if ( availableRamB <= 4_GiB ) + { suggestedSwapSizeB = availableRamB * 2; + } else if ( availableRamB <= 8_GiB ) + { suggestedSwapSizeB = 8_GiB; + } else + { suggestedSwapSizeB = availableRamB; + } // .. top out at 8GiB if we don't care about suspend if ( !ensureSuspendToDisk ) + { suggestedSwapSizeB = qMin( 8_GiB, suggestedSwapSizeB ); + } // Allow for a fudge factor @@ -75,7 +85,9 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) // don't use more than 10% of available space if ( !ensureSuspendToDisk ) + { suggestedSwapSizeB = qMin( suggestedSwapSizeB, qint64( 0.10 * availableSpaceB ) ); + } cDebug() << "Suggested swap size:" << suggestedSwapSizeB / 1024. / 1024. / 1024. << "GiB"; @@ -88,7 +100,9 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) + { defaultFsType = "ext4"; + } bool isEfi = PartUtils::isEfiSystem(); @@ -103,8 +117,8 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO { if ( gs->contains( "efiSystemPartitionSize" ) ) { - CalamaresUtils::Partition::PartitionSize part_size = CalamaresUtils::Partition::PartitionSize( - gs->value( "efiSystemPartitionSize" ).toString() ); + CalamaresUtils::Partition::PartitionSize part_size + = CalamaresUtils::Partition::PartitionSize( gs->value( "efiSystemPartitionSize" ).toString() ); uefisys_part_sizeB = part_size.toBytes( dev->capacity() ); } else @@ -128,15 +142,13 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // firstFreeSector..firstFreeSector+efiSectorCount-1. qint64 lastSector = firstFreeSector + efiSectorCount - 1; core->createPartitionTable( dev, PartitionTable::gpt ); - Partition* efiPartition = KPMHelpers::createNewPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::Fat32, - firstFreeSector, - lastSector, - KPM_PARTITION_FLAG(None) - ); + Partition* efiPartition = KPMHelpers::createNewPartition( dev->partitionTable(), + *dev, + PartitionRole( PartitionRole::Primary ), + FileSystem::Fat32, + firstFreeSector, + lastSector, + KPM_PARTITION_FLAG( None ) ); PartitionInfo::setFormat( efiPartition, true ); PartitionInfo::setMountPoint( efiPartition, o.efiPartitionMountPoint ); core->createPartition( dev, efiPartition, KPM_PARTITION_FLAG_ESP ); @@ -164,7 +176,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO shouldCreateSwap = availableSpaceB > requiredSpaceB; } - qint64 lastSectorForRoot = dev->totalLogical() - 1; //last sector of the device + qint64 lastSectorForRoot = dev->totalLogical() - 1; //last sector of the device if ( shouldCreateSwap ) { lastSectorForRoot -= suggestedSwapSizeB / dev->logicalSize() + 1; @@ -177,28 +189,24 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO Partition* swapPartition = nullptr; if ( o.luksPassphrase.isEmpty() ) { - swapPartition = KPMHelpers::createNewPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::LinuxSwap, - lastSectorForRoot + 1, - dev->totalLogical() - 1, - KPM_PARTITION_FLAG(None) - ); + swapPartition = KPMHelpers::createNewPartition( dev->partitionTable(), + *dev, + PartitionRole( PartitionRole::Primary ), + FileSystem::LinuxSwap, + lastSectorForRoot + 1, + dev->totalLogical() - 1, + KPM_PARTITION_FLAG( None ) ); } else { - swapPartition = KPMHelpers::createNewEncryptedPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::LinuxSwap, - lastSectorForRoot + 1, - dev->totalLogical() - 1, - o.luksPassphrase, - KPM_PARTITION_FLAG(None) - ); + swapPartition = KPMHelpers::createNewEncryptedPartition( dev->partitionTable(), + *dev, + PartitionRole( PartitionRole::Primary ), + FileSystem::LinuxSwap, + lastSectorForRoot + 1, + dev->totalLogical() - 1, + o.luksPassphrase, + KPM_PARTITION_FLAG( None ) ); } PartitionInfo::setFormat( swapPartition, true ); core->createPartition( dev, swapPartition ); @@ -209,10 +217,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO void -doReplacePartition( PartitionCoreModule* core, - Device* dev, - Partition* partition, - Choices::ReplacePartitionOptions o ) +doReplacePartition( PartitionCoreModule* core, Device* dev, Partition* partition, Choices::ReplacePartitionOptions o ) { qint64 firstSector, lastSector; @@ -220,11 +225,15 @@ doReplacePartition( PartitionCoreModule* core, QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) + { defaultFsType = "ext4"; + } PartitionRole newRoles( partition->roles() ); if ( partition->roles().has( PartitionRole::Extended ) ) + { newRoles = PartitionRole( PartitionRole::Primary ); + } if ( partition->roles().has( PartitionRole::Unallocated ) ) { @@ -234,7 +243,9 @@ doReplacePartition( PartitionCoreModule* core, { Partition* parent = dynamic_cast< Partition* >( partition->parent() ); if ( parent && parent->roles().has( PartitionRole::Extended ) ) + { newRoles = PartitionRole( PartitionRole::Logical ); + } } } @@ -242,7 +253,9 @@ doReplacePartition( PartitionCoreModule* core, firstSector = partition->firstSector(); lastSector = partition->lastSector(); if ( !partition->roles().has( PartitionRole::Unallocated ) ) + { core->deletePartition( dev, partition ); + } core->layoutApply( dev, firstSector, lastSector, o.luksPassphrase ); @@ -251,16 +264,14 @@ doReplacePartition( PartitionCoreModule* core, namespace Choices { -static const NamedEnumTable& +static const NamedEnumTable< SwapChoice >& nameTable() { - static const NamedEnumTable names{ - { QStringLiteral( "none" ), SwapChoice::NoSwap }, - { QStringLiteral( "small" ), SwapChoice::SmallSwap }, - { QStringLiteral( "suspend" ), SwapChoice::FullSwap }, - { QStringLiteral( "reuse" ), SwapChoice::ReuseSwap }, - { QStringLiteral( "file" ), SwapChoice::SwapFile } - }; + static const NamedEnumTable< SwapChoice > names { { QStringLiteral( "none" ), SwapChoice::NoSwap }, + { QStringLiteral( "small" ), SwapChoice::SmallSwap }, + { QStringLiteral( "suspend" ), SwapChoice::FullSwap }, + { QStringLiteral( "reuse" ), SwapChoice::ReuseSwap }, + { QStringLiteral( "file" ), SwapChoice::SwapFile } }; return names; } diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index cc9716123..ed7045822 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -33,45 +33,49 @@ namespace PartitionActions */ namespace Choices { - /** @brief Ccchoice of swap (size and type) */ - enum SwapChoice +/** @brief Ccchoice of swap (size and type) */ +enum SwapChoice +{ + NoSwap, // don't create any swap, don't use any + ReuseSwap, // don't create, but do use existing + SmallSwap, // up to 8GiB of swap + FullSwap, // ensureSuspendToDisk -- at least RAM size + SwapFile // use a file (if supported) +}; + +SwapChoice nameToChoice( QString name, bool& ok ); +QString choiceToName( SwapChoice ); + +struct ReplacePartitionOptions +{ + QString defaultFsType; // e.g. "ext4" or "btrfs" + QString luksPassphrase; // optional + + ReplacePartitionOptions( const QString& fs, const QString& luks ) + : defaultFsType( fs ) + , luksPassphrase( luks ) { - NoSwap, // don't create any swap, don't use any - ReuseSwap, // don't create, but do use existing - SmallSwap, // up to 8GiB of swap - FullSwap, // ensureSuspendToDisk -- at least RAM size - SwapFile // use a file (if supported) - }; + } +}; - SwapChoice nameToChoice( QString name, bool& ok ); - QString choiceToName( SwapChoice ); +struct AutoPartitionOptions : ReplacePartitionOptions +{ + QString efiPartitionMountPoint; // optional, e.g. "/boot" + quint64 requiredSpaceB; // estimated required space for root partition + SwapChoice swap; - struct ReplacePartitionOptions + AutoPartitionOptions( const QString& fs, + const QString& luks, + const QString& efi, + qint64 requiredBytes, + SwapChoice s ) + : ReplacePartitionOptions( fs, luks ) + , efiPartitionMountPoint( efi ) + , requiredSpaceB( requiredBytes > 0 ? static_cast< quint64 >( requiredBytes ) : 0 ) + , swap( s ) { - QString defaultFsType; // e.g. "ext4" or "btrfs" - QString luksPassphrase; // optional - - ReplacePartitionOptions( const QString& fs, const QString& luks ) - : defaultFsType( fs ) - , luksPassphrase( luks ) - { - } - }; - - struct AutoPartitionOptions : ReplacePartitionOptions - { - QString efiPartitionMountPoint; // optional, e.g. "/boot" - quint64 requiredSpaceB; // estimated required space for root partition - SwapChoice swap; - - AutoPartitionOptions( const QString& fs, const QString& luks, const QString& efi, qint64 requiredBytes, SwapChoice s ) - : ReplacePartitionOptions( fs, luks ) - , efiPartitionMountPoint( efi ) - , requiredSpaceB( requiredBytes > 0 ? static_cast( requiredBytes ) : 0 ) - , swap( s ) - { - } - }; + } +}; } // namespace Choices @@ -81,9 +85,7 @@ namespace Choices * @param dev the device to wipe. * @param options settings for autopartitioning. */ -void doAutopartition( PartitionCoreModule* core, - Device* dev, - Choices::AutoPartitionOptions options ); +void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions options ); /** * @brief doReplacePartition sets up replace-partitioning with the given partition. @@ -100,4 +102,4 @@ void doReplacePartition( PartitionCoreModule* core, Choices::ReplacePartitionOptions options ); } // namespace PartitionActions -#endif // PARTITIONACTIONS_H +#endif // PARTITIONACTIONS_H diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 4b23c86e4..5d4d8f3cd 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -26,11 +26,10 @@ #include "core/ColorUtils.h" #include "core/DeviceList.h" #include "core/DeviceModel.h" -#include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" -#include "core/PartitionModel.h" #include "core/KPMHelpers.h" #include "core/PartUtils.h" +#include "core/PartitionInfo.h" +#include "core/PartitionModel.h" #include "jobs/ClearMountsJob.h" #include "jobs/ClearTempMountsJob.h" #include "jobs/CreatePartitionJob.h" @@ -45,33 +44,37 @@ #include "jobs/ResizeVolumeGroupJob.h" #include "jobs/SetPartitionFlagsJob.h" -#include "utils/Variant.h" - #ifdef DEBUG_PARTITION_LAME #include "JobExample.h" #endif +#include "partition/PartitionIterator.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" +#include "utils/Variant.h" // KPMcore +#include +#include #include #include #include #include -#include -#include #include #include #include // Qt -#include #include -#include #include +#include +#include #include +using CalamaresUtils::Partition::isPartitionFreeSpace; +using CalamaresUtils::Partition::isPartitionNew; +using CalamaresUtils::Partition::PartitionIterator; -PartitionCoreModule::RefreshHelper::RefreshHelper(PartitionCoreModule* module) +PartitionCoreModule::RefreshHelper::RefreshHelper( PartitionCoreModule* module ) : m_module( module ) { } @@ -99,7 +102,7 @@ private: // called in *reverse* order of declaration in this class. PartitionCoreModule::RefreshHelper m_coreHelper; PartitionModel::ResetHelper m_modelHelper; -} ; +}; //- DeviceInfo --------------------------------------------- @@ -108,19 +111,20 @@ PartitionCoreModule::DeviceInfo::DeviceInfo( Device* _device ) , partitionModel( new PartitionModel ) , immutableDevice( new Device( *_device ) ) , isAvailable( true ) -{} - -PartitionCoreModule::DeviceInfo::~DeviceInfo() { } +PartitionCoreModule::DeviceInfo::~DeviceInfo() {} + void PartitionCoreModule::DeviceInfo::forgetChanges() { jobs.clear(); for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it ) + { PartitionInfo::reset( *it ); + } partitionModel->revert(); } @@ -129,11 +133,15 @@ bool PartitionCoreModule::DeviceInfo::isDirty() const { if ( !jobs.isEmpty() ) + { return true; + } for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it ) if ( PartitionInfo::isDirty( *it ) ) + { return true; + } return false; } @@ -144,8 +152,10 @@ PartitionCoreModule::PartitionCoreModule( QObject* parent ) , m_deviceModel( new DeviceModel( this ) ) , m_bootLoaderModel( new BootLoaderModel( this ) ) { - if ( !KPMHelpers::initKPMcore() ) + if ( !m_kpmcore ) + { qFatal( "Failed to initialize KPMcore backend" ); + } } @@ -194,33 +204,39 @@ PartitionCoreModule::doInit() for ( auto deviceInfo : m_deviceInfos ) { for ( auto it = PartitionIterator::begin( deviceInfo->device.data() ); - it != PartitionIterator::end( deviceInfo->device.data() ); ++it ) + it != PartitionIterator::end( deviceInfo->device.data() ); + ++it ) { Partition* partition = *it; - for ( auto jt = m_osproberLines.begin(); - jt != m_osproberLines.end(); ++jt ) + for ( auto jt = m_osproberLines.begin(); jt != m_osproberLines.end(); ++jt ) { - if ( jt->path == partition->partitionPath() && - partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() ) + if ( jt->path == partition->partitionPath() + && partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() ) + { jt->uuid = partition->fileSystem().uuid(); + } } } } for ( auto deviceInfo : m_deviceInfos ) + { deviceInfo->partitionModel->init( deviceInfo->device.data(), m_osproberLines ); + } DeviceList bootLoaderDevices; - for ( DeviceList::Iterator it = devices.begin(); it != devices.end(); ++it) - if ( (*it)->type() != Device::Type::Disk_Device ) + for ( DeviceList::Iterator it = devices.begin(); it != devices.end(); ++it ) + if ( ( *it )->type() != Device::Type::Disk_Device ) { cDebug() << "Ignoring device that is not Disk_Device to bootLoaderDevices list."; continue; } else - bootLoaderDevices.append(*it); + { + bootLoaderDevices.append( *it ); + } m_bootLoaderModel->init( bootLoaderDevices ); @@ -229,7 +245,9 @@ PartitionCoreModule::doInit() //FIXME: this should be removed in favor of // proper KPM support for EFI if ( PartUtils::isEfiSystem() ) + { scanForEfiSystemPartitions(); + } } PartitionCoreModule::~PartitionCoreModule() @@ -264,7 +282,9 @@ PartitionCoreModule::immutableDeviceCopy( const Device* device ) Q_ASSERT( device ); DeviceInfo* info = infoForDevice( device ); if ( !info ) + { return nullptr; + } return info->immutableDevice.data(); } @@ -288,9 +308,7 @@ PartitionCoreModule::createPartitionTable( Device* device, PartitionTable::Table } void -PartitionCoreModule::createPartition( Device* device, - Partition* partition, - PartitionTable::Flags flags ) +PartitionCoreModule::createPartition( Device* device, Partition* partition, PartitionTable::Flags flags ) { auto deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -301,7 +319,7 @@ PartitionCoreModule::createPartition( Device* device, deviceInfo->jobs << Calamares::job_ptr( job ); - if ( flags != KPM_PARTITION_FLAG(None) ) + if ( flags != KPM_PARTITION_FLAG( None ) ) { SetPartFlagsJob* fJob = new SetPartFlagsJob( device, partition, flags ); deviceInfo->jobs << Calamares::job_ptr( fJob ); @@ -310,21 +328,23 @@ PartitionCoreModule::createPartition( Device* device, } void -PartitionCoreModule::createVolumeGroup( QString &vgName, - QVector< const Partition* > pvList, - qint32 peSize ) +PartitionCoreModule::createVolumeGroup( QString& vgName, QVector< const Partition* > pvList, qint32 peSize ) { // Appending '_' character in case of repeated VG name while ( hasVGwithThisName( vgName ) ) - vgName.append('_'); + { + vgName.append( '_' ); + } CreateVolumeGroupJob* job = new CreateVolumeGroupJob( vgName, pvList, peSize ); job->updatePreview(); - LvmDevice* device = new LvmDevice(vgName); + LvmDevice* device = new LvmDevice( vgName ); for ( const Partition* p : pvList ) + { device->physicalVolumes() << p; + } DeviceInfo* deviceInfo = new DeviceInfo( device ); @@ -339,7 +359,7 @@ PartitionCoreModule::createVolumeGroup( QString &vgName, } void -PartitionCoreModule::resizeVolumeGroup( LvmDevice *device, QVector< const Partition* >& pvList ) +PartitionCoreModule::resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList ) { DeviceInfo* deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -352,7 +372,7 @@ PartitionCoreModule::resizeVolumeGroup( LvmDevice *device, QVector< const Partit } void -PartitionCoreModule::deactivateVolumeGroup( LvmDevice *device ) +PartitionCoreModule::deactivateVolumeGroup( LvmDevice* device ) { DeviceInfo* deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -368,7 +388,7 @@ PartitionCoreModule::deactivateVolumeGroup( LvmDevice *device ) } void -PartitionCoreModule::removeVolumeGroup( LvmDevice *device ) +PartitionCoreModule::removeVolumeGroup( LvmDevice* device ) { DeviceInfo* deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -395,29 +415,36 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition ) // deleting them, so let's play it safe and keep our own list. QList< Partition* > lst; for ( auto childPartition : partition->children() ) - if ( !KPMHelpers::isPartitionFreeSpace( childPartition ) ) + if ( !isPartitionFreeSpace( childPartition ) ) + { lst << childPartition; + } for ( auto childPartition : lst ) + { deletePartition( device, childPartition ); + } } Calamares::JobList& jobs = deviceInfo->jobs; - if ( partition->state() == KPM_PARTITION_STATE(New) ) + if ( partition->state() == KPM_PARTITION_STATE( New ) ) { // First remove matching SetPartFlagsJobs for ( auto it = jobs.begin(); it != jobs.end(); ) { SetPartFlagsJob* job = qobject_cast< SetPartFlagsJob* >( it->data() ); if ( job && job->partition() == partition ) + { it = jobs.erase( it ); + } else + { ++it; + } } // Find matching CreatePartitionJob - auto it = std::find_if( jobs.begin(), jobs.end(), [ partition ]( Calamares::job_ptr job ) - { + auto it = std::find_if( jobs.begin(), jobs.end(), [partition]( Calamares::job_ptr job ) { CreatePartitionJob* createJob = qobject_cast< CreatePartitionJob* >( job.data() ); return createJob && createJob->partition() == partition; } ); @@ -427,7 +454,7 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition ) return; } // Remove it - if ( ! partition->parent()->remove( partition ) ) + if ( !partition->parent()->remove( partition ) ) { cDebug() << "Failed to remove partition from preview"; return; @@ -446,9 +473,13 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition ) { PartitionJob* job = qobject_cast< PartitionJob* >( it->data() ); if ( job && job->partition() == partition ) + { it = jobs.erase( it ); + } else + { ++it; + } } DeletePartitionJob* job = new DeletePartitionJob( device, partition ); job->updatePreview(); @@ -468,10 +499,7 @@ PartitionCoreModule::formatPartition( Device* device, Partition* partition ) } void -PartitionCoreModule::resizePartition( Device* device, - Partition* partition, - qint64 first, - qint64 last ) +PartitionCoreModule::resizePartition( Device* device, Partition* partition, qint64 first, qint64 last ) { auto deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -483,9 +511,7 @@ PartitionCoreModule::resizePartition( Device* device, } void -PartitionCoreModule::setPartitionFlags( Device* device, - Partition* partition, - PartitionTable::Flags flags ) +PartitionCoreModule::setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ) { auto deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -518,7 +544,9 @@ PartitionCoreModule::jobs() const for ( auto info : m_deviceInfos ) { if ( info->isDirty() ) + { lst << Calamares::job_ptr( new ClearMountsJob( info->device.data() ) ); + } } for ( auto info : m_deviceInfos ) @@ -552,18 +580,18 @@ PartitionCoreModule::lvmPVs() const bool PartitionCoreModule::hasVGwithThisName( const QString& name ) const { - auto condition = [ name ]( DeviceInfo* d ) { - return dynamic_cast(d->device.data()) && d->device.data()->name() == name; + auto condition = [name]( DeviceInfo* d ) { + return dynamic_cast< LvmDevice* >( d->device.data() ) && d->device.data()->name() == name; }; return std::find_if( m_deviceInfos.begin(), m_deviceInfos.end(), condition ) != m_deviceInfos.end(); } bool -PartitionCoreModule::isInVG( const Partition *partition ) const +PartitionCoreModule::isInVG( const Partition* partition ) const { - auto condition = [ partition ]( DeviceInfo* d ) { - LvmDevice* vg = dynamic_cast( d->device.data()); + auto condition = [partition]( DeviceInfo* d ) { + LvmDevice* vg = dynamic_cast< LvmDevice* >( d->device.data() ); return vg && vg->physicalVolumes().contains( partition ); }; @@ -578,7 +606,9 @@ PartitionCoreModule::dumpQueue() const { cDebug() << "## Device:" << info->device->name(); for ( auto job : info->jobs ) + { cDebug() << "-" << job->prettyName(); + } } } @@ -612,16 +642,21 @@ PartitionCoreModule::refreshAfterModelChange() //FIXME: this should be removed in favor of // proper KPM support for EFI if ( PartUtils::isEfiSystem() ) + { scanForEfiSystemPartitions(); + } } -void PartitionCoreModule::updateHasRootMountPoint() +void +PartitionCoreModule::updateHasRootMountPoint() { bool oldValue = m_hasRootMountPoint; m_hasRootMountPoint = findPartitionByMountPoint( "/" ); if ( oldValue != m_hasRootMountPoint ) + { hasRootMountPointChanged( m_hasRootMountPoint ); + } } void @@ -636,7 +671,9 @@ PartitionCoreModule::updateIsDirty() break; } if ( oldValue != m_isDirty ) + { isDirtyChanged( m_isDirty ); + } } void @@ -647,16 +684,17 @@ PartitionCoreModule::scanForEfiSystemPartitions() QList< Device* > devices; for ( int row = 0; row < deviceModel()->rowCount(); ++row ) { - Device* device = deviceModel()->deviceForIndex( - deviceModel()->index( row ) ); + Device* device = deviceModel()->deviceForIndex( deviceModel()->index( row ) ); devices.append( device ); } - QList< Partition* > efiSystemPartitions = - KPMHelpers::findPartitions( devices, PartUtils::isEfiBootable ); + QList< Partition* > efiSystemPartitions + = CalamaresUtils::Partition::findPartitions( devices, PartUtils::isEfiBootable ); if ( efiSystemPartitions.isEmpty() ) + { cWarning() << "system is EFI but no EFI system partitions found."; + } m_efiSystemPartitions = efiSystemPartitions; } @@ -671,11 +709,13 @@ PartitionCoreModule::scanForLVMPVs() for ( DeviceInfo* deviceInfo : m_deviceInfos ) { - if ( deviceInfo->device.data()->type() == Device::Type::Disk_Device) + if ( deviceInfo->device.data()->type() == Device::Type::Disk_Device ) + { physicalDevices << deviceInfo->device.data(); + } else if ( deviceInfo->device.data()->type() == Device::Type::LVM_Device ) { - LvmDevice* device = dynamic_cast(deviceInfo->device.data()); + LvmDevice* device = dynamic_cast< LvmDevice* >( deviceInfo->device.data() ); // Restoring physical volume list device->physicalVolumes().clear(); @@ -687,14 +727,9 @@ PartitionCoreModule::scanForLVMPVs() #if defined( WITH_KPMCORE4API ) VolumeManagerDevice::scanDevices( physicalDevices ); for ( auto p : LVM::pvList::list() ) -#else -#if defined( WITH_KPMCORE331API ) - LvmDevice::scanSystemLVM( physicalDevices ); - for ( auto p : LVM::pvList::list() ) #else LvmDevice::scanSystemLVM( physicalDevices ); for ( auto p : LVM::pvList ) -#endif #endif { m_lvmPVs << p.partition().data(); @@ -713,29 +748,35 @@ PartitionCoreModule::scanForLVMPVs() for ( auto job : d->jobs ) { // Including new LVM PVs - CreatePartitionJob* partJob = dynamic_cast( job.data() ); + CreatePartitionJob* partJob = dynamic_cast< CreatePartitionJob* >( job.data() ); if ( partJob ) { Partition* p = partJob->partition(); if ( p->fileSystem().type() == FileSystem::Type::Lvm2_PV ) + { m_lvmPVs << p; + } else if ( p->fileSystem().type() == FileSystem::Type::Luks ) { // Encrypted LVM PVs - FileSystem* innerFS = static_cast(&p->fileSystem())->innerFS(); + FileSystem* innerFS = static_cast< const FS::luks* >( &p->fileSystem() )->innerFS(); if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) + { m_lvmPVs << p; + } } -#ifdef WITH_KPMCORE4API +#if defined( WITH_KPMCORE4API ) else if ( p->fileSystem().type() == FileSystem::Type::Luks2 ) { // Encrypted LVM PVs - FileSystem* innerFS = static_cast(&p->fileSystem())->innerFS(); + FileSystem* innerFS = static_cast< const FS::luks* >( &p->fileSystem() )->innerFS(); if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) + { m_lvmPVs << p; + } } #endif } @@ -746,13 +787,16 @@ PartitionCoreModule::scanForLVMPVs() PartitionCoreModule::DeviceInfo* PartitionCoreModule::infoForDevice( const Device* device ) const { - for ( auto it = m_deviceInfos.constBegin(); - it != m_deviceInfos.constEnd(); ++it ) + for ( auto it = m_deviceInfos.constBegin(); it != m_deviceInfos.constEnd(); ++it ) { if ( ( *it )->device.data() == device ) + { return *it; + } if ( ( *it )->immutableDevice.data() == device ) + { return *it; + } } return nullptr; } @@ -765,7 +809,9 @@ PartitionCoreModule::findPartitionByMountPoint( const QString& mountPoint ) cons Device* device = deviceInfo->device.data(); for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) if ( PartitionInfo::mountPoint( *it ) == mountPoint ) + { return *it; + } } return nullptr; } @@ -782,7 +828,7 @@ PartitionCoreModule::initLayout() { m_partLayout = new PartitionLayout(); - m_partLayout->addEntry( QString("/"), QString("100%") ); + m_partLayout->addEntry( QString( "/" ), QString( "100%" ) ); } void @@ -798,42 +844,52 @@ PartitionCoreModule::initLayout( const QVariantList& config ) { QVariantMap pentry = r.toMap(); - if ( !pentry.contains( "name" ) || !pentry.contains( "mountPoint" ) || - !pentry.contains( "filesystem" ) || !pentry.contains( "size" ) ) + 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 ); + 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() ) + 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() ) + 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() ) + 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, "mountPoint" ), CalamaresUtils::getString( pentry, "filesystem" ), sizeString, minSizeString, - maxSizeString - ) ) + maxSizeString ) ) { - cError() << "Partition layout entry #" << config.indexOf(r) - << "is invalid, switching to default layout."; - delete( m_partLayout ); + cError() << "Partition layout entry #" << config.indexOf( r ) << "is invalid, switching to default layout."; + delete ( m_partLayout ); initLayout(); break; } @@ -841,7 +897,7 @@ PartitionCoreModule::initLayout( const QVariantList& config ) } void -PartitionCoreModule::layoutApply( Device *dev, +PartitionCoreModule::layoutApply( Device* dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, @@ -849,17 +905,14 @@ 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->execute( dev, firstSector, lastSector, luksPassphrase, parent, role ); - foreach ( Partition *part, partList ) + foreach ( Partition* part, partList ) { if ( part->mountPoint() == "/" ) { - createPartition( dev, part, - part->activeFlags() | ( isEfi ? KPM_PARTITION_FLAG(None) : KPM_PARTITION_FLAG(Boot) ) - ); + createPartition( + dev, part, part->activeFlags() | ( isEfi ? KPM_PARTITION_FLAG( None ) : KPM_PARTITION_FLAG( Boot ) ) ); } else { @@ -869,14 +922,10 @@ PartitionCoreModule::layoutApply( Device *dev, } void -PartitionCoreModule::layoutApply( Device *dev, - qint64 firstSector, - qint64 lastSector, - QString luksPassphrase ) +PartitionCoreModule::layoutApply( Device* dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ) { - layoutApply( dev, firstSector, lastSector, luksPassphrase, dev->partitionTable(), - PartitionRole( PartitionRole::Primary ) - ); + layoutApply( + dev, firstSector, lastSector, luksPassphrase, dev->partitionTable(), PartitionRole( PartitionRole::Primary ) ); } void @@ -897,13 +946,13 @@ PartitionCoreModule::revertAllDevices() for ( auto it = m_deviceInfos.begin(); it != m_deviceInfos.end(); ) { // In new VGs device info, there will be always a CreateVolumeGroupJob as the first job in jobs list - if ( dynamic_cast( ( *it )->device.data() ) ) + if ( dynamic_cast< LvmDevice* >( ( *it )->device.data() ) ) { ( *it )->isAvailable = true; if ( !( *it )->jobs.empty() ) { - CreateVolumeGroupJob* vgJob = dynamic_cast( ( *it )->jobs[0].data() ); + CreateVolumeGroupJob* vgJob = dynamic_cast< CreateVolumeGroupJob* >( ( *it )->jobs[ 0 ].data() ); if ( vgJob ) { @@ -935,7 +984,9 @@ PartitionCoreModule::revertDevice( Device* dev, bool individualRevert ) DeviceInfo* devInfo = infoForDevice( dev ); if ( !devInfo ) + { return; + } devInfo->forgetChanges(); CoreBackend* backend = CoreBackendManager::self()->backend(); Device* newDev = backend->scanDevice( devInfo->device->deviceNode() ); @@ -948,13 +999,17 @@ PartitionCoreModule::revertDevice( Device* dev, bool individualRevert ) for ( DeviceInfo* const info : m_deviceInfos ) { if ( info && !info->device.isNull() && info->device->type() == Device::Type::Disk_Device ) + { devices.append( info->device.data() ); + } } m_bootLoaderModel->init( devices ); if ( individualRevert ) + { refreshAfterModelChange(); + } emit deviceReverted( newDev ); } @@ -963,9 +1018,7 @@ void PartitionCoreModule::asyncRevertDevice( Device* dev, std::function< void() > callback ) { QFutureWatcher< void >* watcher = new QFutureWatcher< void >(); - connect( watcher, &QFutureWatcher< void >::finished, - this, [ watcher, callback ] - { + connect( watcher, &QFutureWatcher< void >::finished, this, [watcher, callback] { callback(); watcher->deleteLater(); } ); @@ -979,7 +1032,9 @@ void PartitionCoreModule::clearJobs() { foreach ( DeviceInfo* deviceInfo, m_deviceInfos ) + { deviceInfo->forgetChanges(); + } updateIsDirty(); } @@ -991,11 +1046,13 @@ PartitionCoreModule::isDirty() } bool -PartitionCoreModule::isVGdeactivated( LvmDevice *device ) +PartitionCoreModule::isVGdeactivated( LvmDevice* device ) { for ( DeviceInfo* deviceInfo : m_deviceInfos ) if ( device == deviceInfo->device.data() && !deviceInfo->isAvailable ) + { return true; + } return false; } @@ -1007,7 +1064,9 @@ PartitionCoreModule::createSummaryInfo() const for ( auto deviceInfo : m_deviceInfos ) { if ( !deviceInfo->isDirty() ) + { continue; + } SummaryInfo summaryInfo; summaryInfo.deviceName = deviceInfo->device->name(); summaryInfo.deviceNode = deviceInfo->device->deviceNode(); diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 38a52249f..f88544ae8 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -26,6 +26,7 @@ #include "core/PartitionModel.h" #include "Job.h" +#include "partition/KPMManager.h" // KPMcore #include @@ -138,10 +139,10 @@ public: * If @p flags is not FlagNone, then the given flags are * applied to the newly-created partition. */ - void createPartition( Device* device, Partition* partition, - PartitionTable::Flags flags = KPM_PARTITION_FLAG(None) ); + void + createPartition( Device* device, Partition* partition, PartitionTable::Flags flags = KPM_PARTITION_FLAG( None ) ); - void createVolumeGroup( QString &vgName, QVector< const Partition* > pvList, qint32 peSize ); + void createVolumeGroup( QString& vgName, QVector< const Partition* > pvList, qint32 peSize ); void resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList ); @@ -165,8 +166,13 @@ public: void initLayout(); void initLayout( const QVariantList& config ); - void layoutApply( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); - void layoutApply( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); + void layoutApply( Device* dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); + void layoutApply( Device* dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ); /** * @brief jobs creates and returns a list of jobs which can then apply the changes @@ -195,19 +201,19 @@ public: */ Partition* findPartitionByMountPoint( const QString& mountPoint ) const; - void revert(); // full revert, thread safe, calls doInit - void revertAllDevices(); // convenience function, calls revertDevice + void revert(); // full revert, thread safe, calls doInit + void revertAllDevices(); // convenience function, calls revertDevice /** @brief rescans a single Device and updates DeviceInfo * * When @p individualRevert is true, calls refreshAfterModelChange(), * used to reduce number of refreshes when calling revertAllDevices(). */ - void revertDevice( Device* dev, bool individualRevert=true ); - void asyncRevertDevice( Device* dev, std::function< void() > callback ); //like revertDevice, but asynchronous + void revertDevice( Device* dev, bool individualRevert = true ); + void asyncRevertDevice( Device* dev, std::function< void() > callback ); //like revertDevice, but asynchronous - void clearJobs(); // only clear jobs, the Device* states are preserved + void clearJobs(); // only clear jobs, the Device* states are preserved - bool isDirty(); // true if there are pending changes, otherwise false + bool isDirty(); // true if there are pending changes, otherwise false bool isVGdeactivated( LvmDevice* device ); @@ -224,9 +230,9 @@ public: */ QList< SummaryInfo > createSummaryInfo() const; - const OsproberEntryList osproberEntries() const; // os-prober data structure, cached + const OsproberEntryList osproberEntries() const; // os-prober data structure, cached - void dumpQueue() const; // debug output + void dumpQueue() const; // debug output Q_SIGNALS: void hasRootMountPointChanged( bool value ); @@ -235,6 +241,8 @@ Q_SIGNALS: void deviceReverted( Device* device ); private: + CalamaresUtils::Partition::KPMManager m_kpmcore; + void refreshAfterModelChange(); /** diff --git a/src/modules/partition/core/PartitionInfo.cpp b/src/modules/partition/core/PartitionInfo.cpp index 3a2e5bbd3..fe38bf2d6 100644 --- a/src/modules/partition/core/PartitionInfo.cpp +++ b/src/modules/partition/core/PartitionInfo.cpp @@ -57,15 +57,19 @@ setFormat( Partition* partition, bool value ) partition->setProperty( FORMAT_PROPERTY, value ); } -PartitionTable::Flags flags(const Partition* partition) +PartitionTable::Flags +flags( const Partition* partition ) { auto v = partition->property( FLAGS_PROPERTY ); - if (v.type() == QVariant::Int ) - return static_cast( v.toInt() ); + if ( v.type() == QVariant::Int ) + { + return static_cast< PartitionTable::Flags >( v.toInt() ); + } return partition->activeFlags(); } -void setFlags(Partition* partition, PartitionTable::Flags f) +void +setFlags( Partition* partition, PartitionTable::Flags f ) { partition->setProperty( FLAGS_PROPERTY, PartitionTable::Flags::Int( f ) ); } @@ -82,11 +86,11 @@ bool isDirty( Partition* partition ) { if ( LvmDevice::s_DirtyPVs.contains( partition ) ) + { return true; + } - return !mountPoint( partition ).isEmpty() - || format( partition ) - || flags( partition ) != partition->activeFlags(); + return !mountPoint( partition ).isEmpty() || format( partition ) || flags( partition ) != partition->activeFlags(); } -} // namespace +} // namespace PartitionInfo diff --git a/src/modules/partition/core/PartitionInfo.h b/src/modules/partition/core/PartitionInfo.h index a9c391059..9f9cd2d1e 100644 --- a/src/modules/partition/core/PartitionInfo.h +++ b/src/modules/partition/core/PartitionInfo.h @@ -60,6 +60,6 @@ void reset( Partition* partition ); */ bool isDirty( Partition* partition ); -}; +}; // namespace PartitionInfo #endif /* PARTITIONINFO_H */ diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 35b90722a..23332f3f5 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -26,9 +26,9 @@ #include "core/PartitionLayout.h" #include "core/KPMHelpers.h" +#include "core/PartUtils.h" #include "core/PartitionActions.h" #include "core/PartitionInfo.h" -#include "core/PartUtils.h" #include #include @@ -42,9 +42,11 @@ getDefaultFileSystemType() if ( gs->contains( "defaultFileSystemType" ) ) { - PartUtils::findFS( gs->value( "defaultFileSystemType" ).toString(), &defaultFS); + PartUtils::findFS( gs->value( "defaultFileSystemType" ).toString(), &defaultFS ); if ( defaultFS == FileSystem::Unknown ) + { defaultFS = FileSystem::Ext4; + } } return defaultFS; @@ -67,9 +69,7 @@ PartitionLayout::PartitionLayout( const PartitionLayout& layout ) { } -PartitionLayout::~PartitionLayout() -{ -} +PartitionLayout::~PartitionLayout() {} bool PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) @@ -117,7 +117,12 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const } bool -PartitionLayout::addEntry( const QString& label, const QString& mountPoint, const QString& fs, const QString& size, const QString& min, const QString& max ) +PartitionLayout::addEntry( const QString& label, + const QString& mountPoint, + const QString& fs, + const QString& size, + const QString& min, + const QString& max ) { PartitionLayout::PartitionEntry entry( size, min, max ); @@ -136,7 +141,9 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons entry.partMountPoint = mountPoint; PartUtils::findFS( fs, &entry.partFileSystem ); if ( entry.partFileSystem == FileSystem::Unknown ) + { entry.partFileSystem = m_defaultFsType; + } m_partLayout.append( entry ); @@ -144,8 +151,10 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons } QList< Partition* > -PartitionLayout::execute( Device *dev, qint64 firstSector, - qint64 lastSector, QString luksPassphrase, +PartitionLayout::execute( Device* dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ) { @@ -157,9 +166,9 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, // 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, m_partLayout ) + foreach ( const PartitionLayout::PartitionEntry& part, m_partLayout ) { - Partition *currentPartition = nullptr; + Partition* currentPartition = nullptr; qint64 size = -1; // Calculate partition size @@ -169,67 +178,67 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, } else { - cWarning() << "Partition" << part.partMountPoint << "size (" - << size << "sectors) is invalid, skipping..."; + cWarning() << "Partition" << part.partMountPoint << "size (" << size << "sectors) is invalid, skipping..."; continue; } if ( part.partMinSize.isValid() ) + { minSize = part.partMinSize.toSectors( totalSize, dev->logicalSize() ); + } else + { minSize = 0; + } if ( part.partMaxSize.isValid() ) + { maxSize = part.partMaxSize.toSectors( totalSize, dev->logicalSize() ); + } else + { maxSize = availableSize; + } // Make sure we never go under minSize once converted to sectors if ( maxSize < minSize ) { - cWarning() << "Partition" << part.partMountPoint << "max size (" << maxSize - << "sectors) is < min size (" << minSize << "sectors), using min size"; + cWarning() << "Partition" << part.partMountPoint << "max size (" << maxSize << "sectors) is < min size (" + << minSize << "sectors), using min size"; maxSize = minSize; } // Adjust partition size based on user-defined boundaries and available space if ( size < minSize ) + { size = minSize; + } if ( size > maxSize ) + { size = maxSize; + } if ( size > availableSize ) + { size = availableSize; + } end = firstSector + size - 1; if ( luksPassphrase.isEmpty() ) { currentPartition = KPMHelpers::createNewPartition( - parent, - *dev, - role, - part.partFileSystem, - firstSector, - end, - KPM_PARTITION_FLAG(None) - ); + parent, *dev, role, part.partFileSystem, firstSector, end, KPM_PARTITION_FLAG( None ) ); } else { currentPartition = KPMHelpers::createNewEncryptedPartition( - parent, - *dev, - role, - part.partFileSystem, - firstSector, - end, - luksPassphrase, - KPM_PARTITION_FLAG(None) - ); + parent, *dev, role, part.partFileSystem, firstSector, end, luksPassphrase, KPM_PARTITION_FLAG( None ) ); } 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 ); diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index a9b8d410b..50bb1ba43 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -37,7 +37,6 @@ class Partition; class PartitionLayout { public: - struct PartitionEntry { QString partLabel; @@ -54,9 +53,11 @@ public: bool isValid() const { - if ( !partSize.isValid() || - ( partMinSize.isValid() && partMaxSize.isValid() && partMinSize > partMaxSize ) ) + if ( !partSize.isValid() + || ( partMinSize.isValid() && partMaxSize.isValid() && partMinSize > partMaxSize ) ) + { return false; + } return true; } }; @@ -67,14 +68,27 @@ public: ~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& mountPoint, const QString& fs, const QString& size, const QString& min = QString(), const QString& max = QString() ); + bool addEntry( const QString& mountPoint, + const QString& size, + const QString& min = QString(), + const QString& max = QString() ); + bool addEntry( const QString& label, + const QString& mountPoint, + const QString& fs, + const QString& size, + const QString& min = QString(), + const QString& max = QString() ); /** * @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* > execute( Device* dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ); private: FileSystem::Type m_defaultFsType; diff --git a/src/modules/partition/core/PartitionModel.cpp b/src/modules/partition/core/PartitionModel.cpp index 8b13ab0a0..d6f996c4f 100644 --- a/src/modules/partition/core/PartitionModel.cpp +++ b/src/modules/partition/core/PartitionModel.cpp @@ -20,8 +20,11 @@ #include "core/PartitionModel.h" #include "core/ColorUtils.h" -#include "core/PartitionInfo.h" #include "core/KPMHelpers.h" +#include "core/PartitionInfo.h" + +#include "partition/FileSystem.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" // CalaPM @@ -36,6 +39,9 @@ // Qt #include +using CalamaresUtils::Partition::isPartitionFreeSpace; +using CalamaresUtils::Partition::isPartitionNew; + //- ResetHelper -------------------------------------------- PartitionModel::ResetHelper::ResetHelper( PartitionModel* model ) : m_model( model ) @@ -61,9 +67,9 @@ PartitionModel::PartitionModel( QObject* parent ) } void -PartitionModel::init( Device* device , const OsproberEntryList& osproberEntries ) +PartitionModel::init( Device* device, const OsproberEntryList& osproberEntries ) { - QMutexLocker lock(&m_lock); + QMutexLocker lock( &m_lock ); beginResetModel(); m_device = device; m_osproberEntries = osproberEntries; @@ -81,7 +87,9 @@ PartitionModel::rowCount( const QModelIndex& parent ) const { Partition* parentPartition = partitionForIndex( parent ); if ( parentPartition ) + { return parentPartition->children().count(); + } PartitionTable* table = m_device->partitionTable(); return table ? table->children().count() : 0; } @@ -89,16 +97,21 @@ PartitionModel::rowCount( const QModelIndex& parent ) const QModelIndex PartitionModel::index( int row, int column, const QModelIndex& parent ) const { - PartitionNode* parentPartition = parent.isValid() - ? static_cast< PartitionNode* >( partitionForIndex( parent ) ) - : static_cast< PartitionNode* >( m_device->partitionTable() ); + PartitionNode* parentPartition = parent.isValid() ? static_cast< PartitionNode* >( partitionForIndex( parent ) ) + : static_cast< PartitionNode* >( m_device->partitionTable() ); if ( !parentPartition ) + { return QModelIndex(); + } auto lst = parentPartition->children(); if ( row < 0 || row >= lst.count() ) + { return QModelIndex(); + } if ( column < 0 || column >= ColumnCount ) + { return QModelIndex(); + } Partition* partition = parentPartition->children().at( row ); return createIndex( row, column, partition ); } @@ -107,19 +120,27 @@ QModelIndex PartitionModel::parent( const QModelIndex& child ) const { if ( !child.isValid() ) + { return QModelIndex(); + } Partition* partition = partitionForIndex( child ); if ( !partition ) + { return QModelIndex(); + } PartitionNode* parentNode = partition->parent(); if ( parentNode == m_device->partitionTable() ) + { return QModelIndex(); + } int row = 0; for ( auto p : m_device->partitionTable()->children() ) { if ( parentNode == p ) + { return createIndex( row, 0, parentNode ); + } ++row; } cWarning() << "No parent found!"; @@ -131,7 +152,9 @@ PartitionModel::data( const QModelIndex& index, int role ) const { Partition* partition = partitionForIndex( index ); if ( !partition ) + { return QVariant(); + } switch ( role ) { @@ -140,19 +163,23 @@ PartitionModel::data( const QModelIndex& index, int role ) const int col = index.column(); if ( col == NameColumn ) { - if ( KPMHelpers::isPartitionFreeSpace( partition ) ) + if ( isPartitionFreeSpace( partition ) ) + { return tr( "Free Space" ); + } else { - return KPMHelpers::isPartitionNew( partition ) - ? tr( "New partition" ) - : partition->partitionPath(); + return isPartitionNew( partition ) ? tr( "New partition" ) : partition->partitionPath(); } } if ( col == FileSystemColumn ) - return KPMHelpers::prettyNameForFileSystemType( partition->fileSystem().type() ); + { + return CalamaresUtils::Partition::prettyNameForFileSystemType( partition->fileSystem().type() ); + } if ( col == MountPointColumn ) + { return PartitionInfo::mountPoint( partition ); + } if ( col == SizeColumn ) { qint64 size = ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); @@ -163,41 +190,48 @@ PartitionModel::data( const QModelIndex& index, int role ) const } case Qt::DecorationRole: if ( index.column() == NameColumn ) + { return ColorUtils::colorForPartition( partition ); + } else + { return QVariant(); + } case Qt::ToolTipRole: { int col = index.column(); QString name; if ( col == NameColumn ) { - if ( KPMHelpers::isPartitionFreeSpace( partition ) ) + if ( isPartitionFreeSpace( partition ) ) + { name = tr( "Free Space" ); + } else { - name = KPMHelpers::isPartitionNew( partition ) - ? tr( "New partition" ) - : partition->partitionPath(); + name = isPartitionNew( partition ) ? tr( "New partition" ) : partition->partitionPath(); } } - QString prettyFileSystem = KPMHelpers::prettyNameForFileSystemType( partition->fileSystem().type() ); + QString prettyFileSystem + = CalamaresUtils::Partition::prettyNameForFileSystemType( partition->fileSystem().type() ); qint64 size = ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); QString prettySize = KFormat().formatByteSize( size ); - return QVariant(name + " " + prettyFileSystem + " " + prettySize); + return QVariant( name + " " + prettyFileSystem + " " + prettySize ); } case SizeRole: return ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); case IsFreeSpaceRole: - return KPMHelpers::isPartitionFreeSpace( partition ); + return isPartitionFreeSpace( partition ); case IsPartitionNewRole: - return KPMHelpers::isPartitionNew( partition ); + return isPartitionNew( partition ); case FileSystemLabelRole: - if ( partition->fileSystem().supportGetLabel() != FileSystem::cmdSupportNone && - !partition->fileSystem().label().isEmpty() ) + if ( partition->fileSystem().supportGetLabel() != FileSystem::cmdSupportNone + && !partition->fileSystem().label().isEmpty() ) + { return partition->fileSystem().label(); + } return QVariant(); case FileSystemTypeRole: @@ -212,40 +246,45 @@ PartitionModel::data( const QModelIndex& index, int role ) const // Osprober roles: case OsproberNameRole: foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() && - osproberEntry.uuid == partition->fileSystem().uuid() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) + { return osproberEntry.prettyName; + } return QVariant(); case OsproberPathRole: foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() && - osproberEntry.uuid == partition->fileSystem().uuid() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) + { return osproberEntry.path; + } return QVariant(); case OsproberCanBeResizedRole: foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() && - osproberEntry.uuid == partition->fileSystem().uuid() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) + { return osproberEntry.canBeResized; + } return QVariant(); case OsproberRawLineRole: foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() && - osproberEntry.uuid == partition->fileSystem().uuid() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) + { return osproberEntry.line; + } return QVariant(); case OsproberHomePartitionPathRole: foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone && - !partition->fileSystem().uuid().isEmpty() && - osproberEntry.uuid == partition->fileSystem().uuid() ) + if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone + && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) + { return osproberEntry.homePath; + } return QVariant(); - // end Osprober roles. + // end Osprober roles. default: return QVariant(); @@ -256,7 +295,9 @@ QVariant PartitionModel::headerData( int section, Qt::Orientation, int role ) const { if ( role != Qt::DisplayRole ) + { return QVariant(); + } switch ( section ) { @@ -277,9 +318,11 @@ PartitionModel::headerData( int section, Qt::Orientation, int role ) const Partition* PartitionModel::partitionForIndex( const QModelIndex& index ) const { - QMutexLocker lock(&m_lock); + QMutexLocker lock( &m_lock ); if ( !index.isValid() ) + { return nullptr; + } return reinterpret_cast< Partition* >( index.internalPointer() ); } diff --git a/src/modules/partition/core/PartitionModel.h b/src/modules/partition/core/PartitionModel.h index f5289254b..7066aa5a5 100644 --- a/src/modules/partition/core/PartitionModel.h +++ b/src/modules/partition/core/PartitionModel.h @@ -61,6 +61,7 @@ public: ResetHelper( const ResetHelper& ) = delete; ResetHelper& operator=( const ResetHelper& ) = delete; + private: PartitionModel* m_model; }; @@ -75,7 +76,7 @@ public: FileSystemLabelRole, FileSystemTypeRole, PartitionPathRole, - PartitionPtrRole, // passed as void*, use sparingly + PartitionPtrRole, // passed as void*, use sparingly OsproberNameRole, OsproberPathRole, OsproberCanBeResizedRole, @@ -89,7 +90,7 @@ public: FileSystemColumn, MountPointColumn, SizeColumn, - ColumnCount // Must remain last + ColumnCount // Must remain last }; PartitionModel( QObject* parent = nullptr ); @@ -108,10 +109,7 @@ public: Partition* partitionForIndex( const QModelIndex& index ) const; - Device* device() const - { - return m_device; - } + Device* device() const { return m_device; } void update(); diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 5e8260dec..aebf9a7f6 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -28,7 +28,6 @@ #include "core/PartitionActions.h" #include "core/PartitionCoreModule.h" #include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" #include "core/PartitionModel.h" #include "BootInfoWidget.h" @@ -40,14 +39,16 @@ #include "ReplaceWidget.h" #include "ScanningDialog.h" -#include "utils/CalamaresUtilsGui.h" +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "partition/PartitionIterator.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" #include "utils/Retranslator.h" #include "utils/Units.h" #include "Branding.h" -#include "GlobalStorage.h" -#include "JobQueue.h" +#include "utils/CalamaresUtilsGui.h" #include #include @@ -65,6 +66,9 @@ #include using PartitionActions::Choices::SwapChoice; +using CalamaresUtils::Partition::PartitionIterator; +using CalamaresUtils::Partition::isPartitionFreeSpace; +using CalamaresUtils::Partition::findPartitionByPath; /** @brief Given a set of swap choices, return a sensible value from it. * @@ -691,7 +695,7 @@ ChoicePage::doAlongsideApply() for ( int i = 0; i < dm->rowCount(); ++i ) { Device* dev = dm->deviceForIndex( dm->index( i ) ); - Partition* candidate = KPMHelpers::findPartitionByPath( { dev }, path ); + Partition* candidate = findPartitionByPath( { dev }, path ); if ( candidate ) { qint64 firstSector = candidate->firstSector(); @@ -754,7 +758,7 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) Partition* selectedPartition = static_cast< Partition* >( current.data( PartitionModel::PartitionPtrRole ) .value< void* >() ); - if ( KPMHelpers::isPartitionFreeSpace( selectedPartition ) ) + if ( isPartitionFreeSpace( selectedPartition ) ) { //NOTE: if the selected partition is free space, we don't deal with // a separate /home partition at all because there's no existing @@ -768,7 +772,7 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) if ( parent && parent->roles().has( PartitionRole::Extended ) ) { newRoles = PartitionRole( PartitionRole::Logical ); - newParent = KPMHelpers::findPartitionByPath( { selectedDevice() }, parent->partitionPath() ); + newParent = findPartitionByPath( { selectedDevice() }, parent->partitionPath() ); } } @@ -782,7 +786,7 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) // We can't use the PartitionPtrRole because we need to make changes to the // main DeviceModel, not the immutable copy. QString partPath = current.data( PartitionModel::PartitionPathRole ).toString(); - selectedPartition = KPMHelpers::findPartitionByPath( { selectedDevice() }, + selectedPartition = findPartitionByPath( { selectedDevice() }, partPath ); if ( selectedPartition ) { @@ -805,7 +809,7 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) gs->value( "defaultFileSystemType" ).toString(), m_encryptWidget->passphrase() } ); - Partition* homePartition = KPMHelpers::findPartitionByPath( { selectedDevice() }, + Partition* homePartition = findPartitionByPath( { selectedDevice() }, *homePartitionPath ); if ( homePartition && doReuseHomePartition ) diff --git a/src/modules/partition/gui/CreatePartitionDialog.cpp b/src/modules/partition/gui/CreatePartitionDialog.cpp index 926df03a3..e69137740 100644 --- a/src/modules/partition/gui/CreatePartitionDialog.cpp +++ b/src/modules/partition/gui/CreatePartitionDialog.cpp @@ -20,7 +20,8 @@ * along with Calamares. If not, see . */ -#include "gui/CreatePartitionDialog.h" +#include "CreatePartitionDialog.h" +#include "ui_CreatePartitionDialog.h" #include "core/ColorUtils.h" #include "core/PartitionInfo.h" @@ -29,20 +30,18 @@ #include "gui/PartitionDialogHelpers.h" #include "gui/PartitionSizeController.h" -#include "ui_CreatePartitionDialog.h" - -#include "utils/Logger.h" #include "GlobalStorage.h" #include "JobQueue.h" +#include "partition/PartitionQuery.h" +#include "partition/FileSystem.h" +#include "utils/Logger.h" -// KPMcore #include #include #include #include #include -// Qt #include #include #include @@ -51,6 +50,9 @@ #include #include +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; + static QSet< FileSystem::Type > s_unmountableFS( { FileSystem::Unformatted, @@ -112,7 +114,7 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* par if ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) { - fsNames << KPMHelpers::userVisibleFS( fs ); // This is put into the combobox + fsNames << userVisibleFS( fs ); // This is put into the combobox if ( fs->type() == defaultFSType ) defaultFsIndex = fsCounter; fsCounter++; @@ -279,7 +281,7 @@ CreatePartitionDialog::checkMountPointSelection() void CreatePartitionDialog::initPartResizerWidget( Partition* partition ) { - QColor color = KPMHelpers::isPartitionFreeSpace( partition ) + QColor color = CalamaresUtils::Partition::isPartitionFreeSpace( partition ) ? ColorUtils::colorForPartitionInFreeSpace( partition ) : ColorUtils::colorForPartition( partition ); m_partitionSizeController->init( m_device, partition, color ); diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp index 6268a2a22..37868c7ff 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/gui/EditExistingPartitionDialog.cpp @@ -23,31 +23,31 @@ */ #include "EditExistingPartitionDialog.h" +#include "ui_EditExistingPartitionDialog.h" #include "core/ColorUtils.h" #include "core/PartitionCoreModule.h" #include "core/PartitionInfo.h" #include "core/PartUtils.h" -#include "core/KPMHelpers.h" #include "gui/PartitionDialogHelpers.h" #include "gui/PartitionSizeController.h" -#include "ui_EditExistingPartitionDialog.h" - #include "GlobalStorage.h" #include "JobQueue.h" +#include "partition/FileSystem.h" #include "utils/Logger.h" -// KPMcore #include #include #include -// Qt #include #include #include +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; + EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partition* partition, const QStringList& usedMountPoints, QWidget* parentWidget ) : QDialog( parentWidget ) , m_ui( new Ui_EditExistingPartitionDialog ) @@ -77,7 +77,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit m_ui->fileSystemComboBox->setEnabled( doFormat ); if ( !doFormat ) - m_ui->fileSystemComboBox->setCurrentText( KPMHelpers::userVisibleFS( m_partition->fileSystem() ) ); + m_ui->fileSystemComboBox->setCurrentText( userVisibleFS( m_partition->fileSystem() ) ); updateMountPointPicker(); } ); @@ -93,7 +93,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit for ( auto fs : FileSystemFactory::map() ) { if ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) - fsNames << KPMHelpers::userVisibleFS( fs ); // For the combo box + fsNames << userVisibleFS( fs ); // For the combo box } m_ui->fileSystemComboBox->addItems( fsNames ); @@ -107,7 +107,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit defaultFSType = FileSystem::Type::Ext4; } - QString thisFSNameForUser = KPMHelpers::userVisibleFS( m_partition->fileSystem() ); + QString thisFSNameForUser = userVisibleFS( m_partition->fileSystem() ); if ( fsNames.contains( thisFSNameForUser ) ) m_ui->fileSystemComboBox->setCurrentText( thisFSNameForUser ); else diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 915f899b2..d2ad49c23 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -40,11 +40,13 @@ #include "ui_PartitionPage.h" #include "ui_CreatePartitionTableDialog.h" +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" #include "utils/Retranslator.h" + #include "Branding.h" -#include "JobQueue.h" -#include "GlobalStorage.h" // KPMcore #include @@ -132,7 +134,7 @@ PartitionPage::updateButtons() Q_ASSERT( model ); Partition* partition = model->partitionForIndex( index ); Q_ASSERT( partition ); - bool isFree = KPMHelpers::isPartitionFreeSpace( partition ); + bool isFree = CalamaresUtils::Partition::isPartitionFreeSpace( partition ); bool isExtended = partition->roles().has( PartitionRole::Extended ); bool isInVG = m_core->isInVG( partition ); @@ -392,7 +394,7 @@ PartitionPage::onEditClicked() Partition* partition = model->partitionForIndex( index ); Q_ASSERT( partition ); - if ( KPMHelpers::isPartitionNew( partition ) ) + if ( CalamaresUtils::Partition::isPartitionNew( partition ) ) updatePartitionToCreate( model->device(), partition ); else editExistingPartition( model->device(), partition ); @@ -452,7 +454,7 @@ PartitionPage::onPartitionViewActivated() // but I don't expect there will be other occurences of triggering the same // action from multiple UI elements in this page, so it does not feel worth // the price. - if ( KPMHelpers::isPartitionFreeSpace( partition ) ) + if ( CalamaresUtils::Partition::isPartitionFreeSpace( partition ) ) m_ui->createButton->click(); else m_ui->editButton->click(); diff --git a/src/modules/partition/gui/PartitionSplitterWidget.cpp b/src/modules/partition/gui/PartitionSplitterWidget.cpp index 0281ab32c..bcc80b65a 100644 --- a/src/modules/partition/gui/PartitionSplitterWidget.cpp +++ b/src/modules/partition/gui/PartitionSplitterWidget.cpp @@ -19,10 +19,12 @@ #include "PartitionSplitterWidget.h" #include "core/ColorUtils.h" -#include "core/PartitionIterator.h" #include "core/KPMHelpers.h" +#include "partition/PartitionIterator.h" +#include "partition/PartitionQuery.h" #include "utils/Logger.h" + #include "utils/CalamaresUtilsGui.h" #include @@ -33,6 +35,8 @@ #include #include +using CalamaresUtils::Partition::PartitionIterator; + static const int VIEW_HEIGHT = qMax( CalamaresUtils::defaultFontHeight() + 8, // wins out with big fonts int( CalamaresUtils::defaultFontHeight() * 0.6 ) + 22 ); // wins out with small fonts static const int CORNER_RADIUS = 3; @@ -66,7 +70,7 @@ PartitionSplitterWidget::init( Device* dev, bool drawNestedPartitions ) PartitionSplitterItem newItem = { ( *it )->partitionPath(), ColorUtils::colorForPartition( *it ), - KPMHelpers::isPartitionFreeSpace( *it ), + CalamaresUtils::Partition::isPartitionFreeSpace( *it ), ( *it )->capacity(), PartitionSplitterItem::Normal, {} diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 4b16d807a..28ed77409 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -75,7 +75,7 @@ PartitionViewStep::PartitionViewStep( QObject* parent ) m_waitingWidget = new WaitingWidget( QString() ); m_widget->addWidget( m_waitingWidget ); - CALAMARES_RETRANSLATE( qobject_cast< WaitingWidget* >( m_waitingWidget )->setText( tr( "Gathering system information..." ) ); ) + CALAMARES_RETRANSLATE( m_waitingWidget->setText( tr( "Gathering system information..." ) ); ) m_core = new PartitionCoreModule( this ); // Unusable before init is complete! // We're not done loading, but we need the configuration map first. diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h index f60dff1df..20e9f4f1c 100644 --- a/src/modules/partition/gui/PartitionViewStep.h +++ b/src/modules/partition/gui/PartitionViewStep.h @@ -35,6 +35,7 @@ class ChoicePage; class PartitionPage; class PartitionCoreModule; class QStackedWidget; +class WaitingWidget; template class QFutureWatcher; @@ -82,7 +83,7 @@ private: ChoicePage* m_choicePage; PartitionPage* m_manualPartitionPage; - QWidget* m_waitingWidget; + WaitingWidget* m_waitingWidget; QFutureWatcher* m_future; QSet< PartitionActions::Choices::SwapChoice > m_swapChoices; diff --git a/src/modules/partition/gui/ReplaceWidget.cpp b/src/modules/partition/gui/ReplaceWidget.cpp index 3d0711761..728b33c36 100644 --- a/src/modules/partition/gui/ReplaceWidget.cpp +++ b/src/modules/partition/gui/ReplaceWidget.cpp @@ -2,7 +2,7 @@ * * Copyright 2014-2015, Teo Mrnjavac * Copyright 2014, Aurélien Gâteau - * Copyright 2019, Adriaan de Groot + * Copyright 2019-2020, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ #include "ui_ReplaceWidget.h" #include "core/DeviceModel.h" -#include "core/KPMHelpers.h" #include "core/PartitionCoreModule.h" #include "core/PartitionActions.h" #include "core/PartitionInfo.h" @@ -30,6 +29,7 @@ #include "Branding.h" #include "GlobalStorage.h" #include "JobQueue.h" +#include "partition/FileSystem.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Retranslator.h" @@ -38,6 +38,9 @@ #include +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; + ReplaceWidget::ReplaceWidget( PartitionCoreModule* core, QComboBox* devicesComboBox, QWidget* parent ) @@ -193,7 +196,7 @@ ReplaceWidget::onPartitionSelected() return; } - QString fsNameForUser = KPMHelpers::userVisibleFS( partition->fileSystem() ); + QString fsNameForUser = userVisibleFS( partition->fileSystem() ); QString prettyName = tr( "Data partition (%1)" ).arg( fsNameForUser ); for ( const QString& line : osproberLines ) { diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp index 605087147..2678a70a3 100644 --- a/src/modules/partition/jobs/ClearMountsJob.cpp +++ b/src/modules/partition/jobs/ClearMountsJob.cpp @@ -21,7 +21,9 @@ #include "ClearMountsJob.h" #include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" + +#include "partition/Sync.h" +#include "partition/PartitionIterator.h" #include "utils/Logger.h" // KPMcore @@ -33,6 +35,7 @@ #include #include +using CalamaresUtils::Partition::PartitionIterator; ClearMountsJob::ClearMountsJob( Device* device ) : Calamares::Job() @@ -57,25 +60,47 @@ ClearMountsJob::prettyStatusMessage() const } +QStringList +getPartitionsForDevice( const QString& deviceName ) +{ + QStringList partitions; + + QFile dev_partitions( "/proc/partitions" ); + if ( dev_partitions.open( QFile::ReadOnly ) ) + { + cDebug() << "Reading from" << dev_partitions.fileName(); + QTextStream in( &dev_partitions ); + (void) in.readLine(); // That's the header line, skip it + while ( !in.atEnd() ) + { + // The fourth column (index from 0, so index 3) is the name of the device; + // keep it if it is followed by something. + QStringList columns = in.readLine().split( ' ', QString::SkipEmptyParts ); + if ( ( columns.count() >= 4 ) && ( columns[3].startsWith( deviceName ) ) && ( columns[3] != deviceName ) ) + { + partitions.append( columns[3] ); + } + } + } + else + { + cDebug() << "Could not open" << dev_partitions.fileName(); + } + + return partitions; +} + Calamares::JobResult ClearMountsJob::exec() { - QStringList goodNews; + CalamaresUtils::Partition::Syncer s; QString deviceName = m_device->deviceNode().split( '/' ).last(); + QStringList goodNews; QProcess process; - process.setProgram( "sh" ); - process.setArguments( { - "-c", - QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" ) - .arg( deviceName ) - } ); - process.start(); - process.waitForFinished(); - const QString partitions = process.readAllStandardOutput(); - const QStringList partitionsList = partitions.simplified().split( ' ' ); + QStringList partitionsList = getPartitionsForDevice( deviceName ); // Build a list of partitions of type 82 (Linux swap / Solaris). // We then need to clear them just in case they contain something resumable from a diff --git a/src/modules/partition/jobs/ClearMountsJob.h b/src/modules/partition/jobs/ClearMountsJob.h index 26514913e..6b98aac08 100644 --- a/src/modules/partition/jobs/ClearMountsJob.h +++ b/src/modules/partition/jobs/ClearMountsJob.h @@ -19,7 +19,7 @@ #ifndef CLEARMOUNTSJOB_H #define CLEARMOUNTSJOB_H -#include +#include "Job.h" class Device; diff --git a/src/modules/partition/jobs/ClearTempMountsJob.h b/src/modules/partition/jobs/ClearTempMountsJob.h index 36adca91b..d7b2c55f4 100644 --- a/src/modules/partition/jobs/ClearTempMountsJob.h +++ b/src/modules/partition/jobs/ClearTempMountsJob.h @@ -19,7 +19,7 @@ #ifndef CLEARTEMPMOUNTSJOB_H #define CLEARTEMPMOUNTSJOB_H -#include +#include "Job.h" class Device; diff --git a/src/modules/partition/jobs/CreatePartitionJob.cpp b/src/modules/partition/jobs/CreatePartitionJob.cpp index 0f9590bfd..afa7b3ecc 100644 --- a/src/modules/partition/jobs/CreatePartitionJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionJob.cpp @@ -18,14 +18,12 @@ * along with Calamares. If not, see . */ -#include "jobs/CreatePartitionJob.h" - -#include "core/KPMHelpers.h" +#include "CreatePartitionJob.h" +#include "partition/FileSystem.h" #include "utils/Logger.h" #include "utils/Units.h" -// KPMcore #include #include #include @@ -34,8 +32,8 @@ #include #include -using KPMHelpers::untranslatedFS; -using KPMHelpers::userVisibleFS; +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; CreatePartitionJob::CreatePartitionJob( Device* device, Partition* partition ) : PartitionJob( partition ) diff --git a/src/modules/partition/jobs/CreatePartitionJob.h b/src/modules/partition/jobs/CreatePartitionJob.h index e25c74241..fe4ab2203 100644 --- a/src/modules/partition/jobs/CreatePartitionJob.h +++ b/src/modules/partition/jobs/CreatePartitionJob.h @@ -20,7 +20,7 @@ #ifndef CREATEPARTITIONJOB_H #define CREATEPARTITIONJOB_H -#include +#include "PartitionJob.h" class Device; class Partition; diff --git a/src/modules/partition/jobs/CreatePartitionTableJob.cpp b/src/modules/partition/jobs/CreatePartitionTableJob.cpp index 3465a0e2d..b18f56a04 100644 --- a/src/modules/partition/jobs/CreatePartitionTableJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionTableJob.cpp @@ -20,21 +20,22 @@ #include "jobs/CreatePartitionTableJob.h" -#include "core/PartitionIterator.h" - +#include "partition/PartitionIterator.h" #include "utils/Logger.h" // KPMcore -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include // Qt #include +using CalamaresUtils::Partition::PartitionIterator; + CreatePartitionTableJob::CreatePartitionTableJob( Device* device, PartitionTable::TableType type ) : m_device( device ) , m_type( type ) @@ -99,7 +100,7 @@ CreatePartitionTableJob::exec() cDebug() << "lsblk:\n" << lsblk.readAllStandardOutput(); QProcess mount; - mount.setProgram( "mount" ); + mount.setProgram( "mount" ); // Debug output only, not mounting something mount.setProcessChannelMode( QProcess::MergedChannels ); mount.start(); mount.waitForFinished(); diff --git a/src/modules/partition/jobs/CreatePartitionTableJob.h b/src/modules/partition/jobs/CreatePartitionTableJob.h index 38ef5365c..d4f65ba51 100644 --- a/src/modules/partition/jobs/CreatePartitionTableJob.h +++ b/src/modules/partition/jobs/CreatePartitionTableJob.h @@ -20,7 +20,8 @@ #ifndef CREATEPARTITIONTABLEJOB_H #define CREATEPARTITIONTABLEJOB_H -#include +#include "Job.h" +#include "partition/KPMManager.h" // KPMcore #include @@ -50,6 +51,7 @@ public: } private: + CalamaresUtils::Partition::KPMManager m_kpmcore; Device* m_device; PartitionTable::TableType m_type; PartitionTable* createTable(); diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.h b/src/modules/partition/jobs/CreateVolumeGroupJob.h index 6f85eaab8..dfdf0319f 100644 --- a/src/modules/partition/jobs/CreateVolumeGroupJob.h +++ b/src/modules/partition/jobs/CreateVolumeGroupJob.h @@ -19,12 +19,13 @@ #ifndef CREATEVOLUMEGROUPJOB_H #define CREATEVOLUMEGROUPJOB_H -#include - -#include +#include "Job.h" +#include "partition/KPMManager.h" #include +class Partition; + class CreateVolumeGroupJob : public Calamares::Job { Q_OBJECT @@ -40,6 +41,7 @@ public: void undoPreview(); private: + CalamaresUtils::Partition::KPMManager m_kpmcore; QString m_vgName; QVector< const Partition* > m_pvList; qint32 m_peSize; diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h index 17be7cdef..ff6569b10 100644 --- a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h +++ b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h @@ -20,6 +20,7 @@ #define DEACTIVATEVOLUMEGROUPJOB_H #include "Job.h" +#include "partition/KPMManager.h" class LvmDevice; @@ -35,6 +36,7 @@ public: Calamares::JobResult exec() override; private: + CalamaresUtils::Partition::KPMManager m_kpmcore; LvmDevice* m_device; }; diff --git a/src/modules/partition/jobs/DeletePartitionJob.cpp b/src/modules/partition/jobs/DeletePartitionJob.cpp index 5cd4a08ea..07880ce65 100644 --- a/src/modules/partition/jobs/DeletePartitionJob.cpp +++ b/src/modules/partition/jobs/DeletePartitionJob.cpp @@ -21,12 +21,12 @@ #include "jobs/DeletePartitionJob.h" // KPMcore -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include DeletePartitionJob::DeletePartitionJob( Device* device, Partition* partition ) : PartitionJob( partition ) diff --git a/src/modules/partition/jobs/DeletePartitionJob.h b/src/modules/partition/jobs/DeletePartitionJob.h index 805689cc0..cdc0b7f63 100644 --- a/src/modules/partition/jobs/DeletePartitionJob.h +++ b/src/modules/partition/jobs/DeletePartitionJob.h @@ -20,7 +20,7 @@ #ifndef DELETEPARTITIONJOB_H #define DELETEPARTITIONJOB_H -#include +#include "PartitionJob.h" class Device; class Partition; diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index c909ba913..65c93014b 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -18,31 +18,31 @@ * along with Calamares. If not, see . */ -#include "jobs/FillGlobalStorageJob.h" +#include "FillGlobalStorageJob.h" #include "core/KPMHelpers.h" #include "core/PartitionInfo.h" -#include "core/PartitionIterator.h" #include "Branding.h" #include "GlobalStorage.h" #include "JobQueue.h" +#include "partition/FileSystem.h" +#include "partition/PartitionIterator.h" #include "utils/Logger.h" -// KPMcore -#include -#include -#include -#include +#include +#include +#include +#include -// Qt #include #include #include #include -using KPMHelpers::untranslatedFS; -using KPMHelpers::userVisibleFS; +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; +using CalamaresUtils::Partition::PartitionIterator; typedef QHash< QString, QString > UuidForPartitionHash; diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.h b/src/modules/partition/jobs/FillGlobalStorageJob.h index 357d939a2..c2bf80a06 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.h +++ b/src/modules/partition/jobs/FillGlobalStorageJob.h @@ -20,7 +20,7 @@ #ifndef FILLGLOBALSTORAGEJOB_H #define FILLGLOBALSTORAGEJOB_H -#include +#include "Job.h" // Qt #include diff --git a/src/modules/partition/jobs/FormatPartitionJob.cpp b/src/modules/partition/jobs/FormatPartitionJob.cpp index c877343c3..b8af7493d 100644 --- a/src/modules/partition/jobs/FormatPartitionJob.cpp +++ b/src/modules/partition/jobs/FormatPartitionJob.cpp @@ -2,6 +2,7 @@ * * Copyright 2014, Aurélien Gâteau * Copyright 2015-2016, Teo Mrnjavac + * Copyright 2020, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,22 +18,20 @@ * along with Calamares. If not, see . */ -#include "jobs/FormatPartitionJob.h" - -#include "core/KPMHelpers.h" +#include "FormatPartitionJob.h" +#include "partition/FileSystem.h" #include "utils/Logger.h" -// KPMcore -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -using KPMHelpers::untranslatedFS; -using KPMHelpers::userVisibleFS; +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; FormatPartitionJob::FormatPartitionJob( Device* device, Partition* partition ) : PartitionJob( partition ) diff --git a/src/modules/partition/jobs/FormatPartitionJob.h b/src/modules/partition/jobs/FormatPartitionJob.h index 683deb66e..9ce4a0677 100644 --- a/src/modules/partition/jobs/FormatPartitionJob.h +++ b/src/modules/partition/jobs/FormatPartitionJob.h @@ -20,7 +20,7 @@ #ifndef FORMATPARTITIONJOB_H #define FORMATPARTITIONJOB_H -#include +#include "PartitionJob.h" class Device; class Partition; diff --git a/src/modules/partition/jobs/PartitionJob.cpp b/src/modules/partition/jobs/PartitionJob.cpp index 1da8b0ba0..6adf99122 100644 --- a/src/modules/partition/jobs/PartitionJob.cpp +++ b/src/modules/partition/jobs/PartitionJob.cpp @@ -16,7 +16,7 @@ * along with Calamares. If not, see . */ -#include +#include "PartitionJob.h" PartitionJob::PartitionJob( Partition* partition ) : m_partition( partition ) diff --git a/src/modules/partition/jobs/PartitionJob.h b/src/modules/partition/jobs/PartitionJob.h index 61245203c..4cb5e5db6 100644 --- a/src/modules/partition/jobs/PartitionJob.h +++ b/src/modules/partition/jobs/PartitionJob.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Aurélien Gâteau + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,12 +20,13 @@ #ifndef PARTITIONJOB_H #define PARTITIONJOB_H -#include +#include "Job.h" +#include "partition/KPMManager.h" class Partition; /** - * Base class for jobs which affect a partition. + * Base class for jobs which affect a partition and which use KPMCore. */ class PartitionJob : public Calamares::Job { @@ -46,6 +48,7 @@ public slots: void iprogress( int percent ); protected: + CalamaresUtils::Partition::KPMManager m_kpmcore; Partition* m_partition; }; diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.h b/src/modules/partition/jobs/RemoveVolumeGroupJob.h index 009e6f44d..8687eb544 100644 --- a/src/modules/partition/jobs/RemoveVolumeGroupJob.h +++ b/src/modules/partition/jobs/RemoveVolumeGroupJob.h @@ -19,7 +19,8 @@ #ifndef REMOVEVOLUMEGROUPJOB_H #define REMOVEVOLUMEGROUPJOB_H -#include +#include "Job.h" +#include "partition/KPMManager.h" class LvmDevice; @@ -35,6 +36,7 @@ public: Calamares::JobResult exec() override; private: + CalamaresUtils::Partition::KPMManager m_kpmcore; LvmDevice* m_device; }; diff --git a/src/modules/partition/jobs/ResizePartitionJob.cpp b/src/modules/partition/jobs/ResizePartitionJob.cpp index bac4c7a6c..ebc47d286 100644 --- a/src/modules/partition/jobs/ResizePartitionJob.cpp +++ b/src/modules/partition/jobs/ResizePartitionJob.cpp @@ -23,9 +23,9 @@ #include "utils/Units.h" // KPMcore -#include -#include -#include +#include +#include +#include using CalamaresUtils::BytesToMiB; diff --git a/src/modules/partition/jobs/ResizePartitionJob.h b/src/modules/partition/jobs/ResizePartitionJob.h index 9e6d39943..f8413f214 100644 --- a/src/modules/partition/jobs/ResizePartitionJob.h +++ b/src/modules/partition/jobs/ResizePartitionJob.h @@ -20,7 +20,7 @@ #ifndef RESIZEPARTITIONJOB_H #define RESIZEPARTITIONJOB_H -#include +#include "PartitionJob.h" class Device; class Partition; diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.h b/src/modules/partition/jobs/ResizeVolumeGroupJob.h index fb0ff715b..1519dfa9d 100644 --- a/src/modules/partition/jobs/ResizeVolumeGroupJob.h +++ b/src/modules/partition/jobs/ResizeVolumeGroupJob.h @@ -19,7 +19,8 @@ #ifndef RESIZEVOLUMEGROUPJOB_H #define RESIZEVOLUMEGROUPJOB_H -#include +#include "Job.h" +#include "partition/KPMManager.h" #include @@ -42,6 +43,7 @@ private: QString targetPartitions() const; private: + CalamaresUtils::Partition::KPMManager m_kpmcore; LvmDevice* m_device; QVector< const Partition* > m_partitionList; }; diff --git a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp b/src/modules/partition/jobs/SetPartitionFlagsJob.cpp index 09380a24c..7298e9bd0 100644 --- a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp +++ b/src/modules/partition/jobs/SetPartitionFlagsJob.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2016, Teo Mrnjavac + * Copyright 2020, Adriaan de Groot * * Based on the SetPartFlagsJob class from KDE Partition Manager, * Copyright 2008, 2010, Volker Lanz @@ -21,21 +22,19 @@ #include "SetPartitionFlagsJob.h" -#include "core/KPMHelpers.h" - +#include "partition/FileSystem.h" #include "utils/Logger.h" #include "utils/Units.h" -// KPMcore -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include using CalamaresUtils::BytesToMiB; -using KPMHelpers::untranslatedFS; -using KPMHelpers::userVisibleFS; +using CalamaresUtils::Partition::untranslatedFS; +using CalamaresUtils::Partition::userVisibleFS; SetPartFlagsJob::SetPartFlagsJob( Device* device, Partition* partition, diff --git a/src/modules/partition/jobs/SetPartitionFlagsJob.h b/src/modules/partition/jobs/SetPartitionFlagsJob.h index 464ad0c6b..30cad9a21 100644 --- a/src/modules/partition/jobs/SetPartitionFlagsJob.h +++ b/src/modules/partition/jobs/SetPartitionFlagsJob.h @@ -22,7 +22,7 @@ #ifndef SETPARTITIONFLAGSJOB_H #define SETPARTITIONFLAGSJOB_H -#include +#include "PartitionJob.h" #include diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt index fdba7e688..a64d7620e 100644 --- a/src/modules/partition/tests/CMakeLists.txt +++ b/src/modules/partition/tests/CMakeLists.txt @@ -26,7 +26,16 @@ calamares_add_test( SOURCES ${partitionjobtests_SRCS} LIBRARIES kpmcore + DEFINITIONS ${_partition_defs} ) -if( TARGET partitionjobtests ) - target_compile_definitions( partitionjobtests PRIVATE ${_partition_defs} ) -endif() + +calamares_add_test( + clearmountsjobtests + SOURCES + ${PartitionModule_SOURCE_DIR}/jobs/ClearMountsJob.cpp + ClearMountsJobTests.cpp + LIBRARIES + kpmcore + DEFINITIONS ${_partition_defs} +) + diff --git a/src/modules/partition/tests/ClearMountsJobTests.cpp b/src/modules/partition/tests/ClearMountsJobTests.cpp new file mode 100644 index 000000000..1f01c4638 --- /dev/null +++ b/src/modules/partition/tests/ClearMountsJobTests.cpp @@ -0,0 +1,66 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "ClearMountsJobTests.h" + +#include "utils/Logger.h" + +#include + +QTEST_GUILESS_MAIN( ClearMountsJobTests ) + + +/* Not exactly public API */ +QStringList +getPartitionsForDevice( const QString& deviceName ); + +QStringList +getPartitionsForDevice_other(const QString& deviceName) +{ + QProcess process; + process.setProgram( "sh" ); + process.setArguments( { + "-c", + QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" ) + .arg( deviceName ) + } ); + process.start(); + process.waitForFinished(); + + const QString partitions = process.readAllStandardOutput(); + const QStringList partitionsList = partitions.simplified().split( ' ' ); + + return partitionsList; +} + + +ClearMountsJobTests::ClearMountsJobTests() +{ + Logger::setupLogLevel(6); +} + +void ClearMountsJobTests::testFindPartitions() +{ + QStringList partitions = getPartitionsForDevice( "sda" ); + QStringList other_part = getPartitionsForDevice_other( "sda" ); + + cDebug() << "Initial implementation:" << Logger::DebugList( partitions ); + cDebug() << "Other implementation:" << Logger::DebugList( other_part ); + + QCOMPARE( partitions, other_part ); +} diff --git a/src/modules/partition/tests/ClearMountsJobTests.h b/src/modules/partition/tests/ClearMountsJobTests.h new file mode 100644 index 000000000..0cc2b5c78 --- /dev/null +++ b/src/modules/partition/tests/ClearMountsJobTests.h @@ -0,0 +1,34 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares 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. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef CLEARMOUNTSJOBTESTS_H +#define CLEARMOUNTSJOBTESTS_H + +#include + +class ClearMountsJobTests : public QObject +{ + Q_OBJECT +public: + ClearMountsJobTests(); + +private Q_SLOTS: + void testFindPartitions(); +}; + +#endif diff --git a/src/modules/partition/tests/PartitionJobTests.cpp b/src/modules/partition/tests/PartitionJobTests.cpp index f3bd8dd13..7684ad7a8 100644 --- a/src/modules/partition/tests/PartitionJobTests.cpp +++ b/src/modules/partition/tests/PartitionJobTests.cpp @@ -19,16 +19,18 @@ #include +#include "partition/KPMManager.h" +#include "partition/PartitionQuery.h" +#include "utils/Logger.h" #include "utils/Units.h" +#include #include #include #include -#include // CalaPM #include -#include #include // Qt @@ -40,6 +42,7 @@ QTEST_GUILESS_MAIN( PartitionJobTests ) using namespace Calamares; using CalamaresUtils::operator""_MiB; +using CalamaresUtils::Partition::isPartitionFreeSpace; class PartitionMounter { @@ -56,15 +59,14 @@ public: ~PartitionMounter() { if ( !m_mounted ) + { return; + } int ret = QProcess::execute( "umount", QStringList() << m_mountPointDir.path() ); QCOMPARE( ret, 0 ); } - QString mountPoint() const - { - return m_mounted ? m_mountPointDir.path() : QString(); - } + QString mountPoint() const { return m_mounted ? m_mountPointDir.path() : QString(); } private: QString m_devicePath; @@ -77,9 +79,9 @@ static QByteArray generateTestData( qint64 size ) { QByteArray ba; - ba.resize( static_cast( size ) ); + ba.resize( static_cast< int >( size ) ); // Fill the array explicitly to keep Valgrind happy - for ( auto it = ba.data() ; it < ba.data() + size ; ++it ) + for ( auto it = ba.data(); it < ba.data() + size; ++it ) { *it = char( rand() & 0xff ); } @@ -102,9 +104,9 @@ writeFile( const QString& path, const QByteArray data ) if ( count < 0 ) { QString msg = QString( "Writing file failed. Only %1 bytes written out of %2. Error: '%3'." ) - .arg( ptr - data.constData() ) - .arg( data.size() ) - .arg( file.errorString() ); + .arg( ptr - data.constData() ) + .arg( data.size() ) + .arg( file.errorString() ); QFAIL( qPrintable( msg ) ); } ptr += count; @@ -114,9 +116,11 @@ writeFile( const QString& path, const QByteArray data ) static Partition* firstFreePartition( PartitionNode* parent ) { - for( auto child : parent->children() ) - if ( KPMHelpers::isPartitionFreeSpace( child ) ) + for ( auto child : parent->children() ) + if ( isPartitionFreeSpace( child ) ) + { return child; + } return nullptr; } @@ -143,7 +147,9 @@ QueueRunner::run() m_queue->start(); QEventLoop loop; while ( !m_finished ) + { loop.processEvents(); + } return m_success; } @@ -161,10 +167,13 @@ QueueRunner::onFailed( const QString& message, const QString& details ) QFAIL( qPrintable( msg ) ); } +CalamaresUtils::Partition::KPMManager* kpmcore = nullptr; + //- PartitionJobTests ------------------------------------------------------------------ PartitionJobTests::PartitionJobTests() : m_runner( &m_queue ) -{} +{ +} void PartitionJobTests::initTestCase() @@ -173,21 +182,27 @@ PartitionJobTests::initTestCase() if ( devicePath.isEmpty() ) { // The 0 is to keep the macro parameters happy - QSKIP( "Skipping test, CALAMARES_TEST_DISK is not set. It should point to a disk which can be safely formatted", 0 ); + QSKIP( "Skipping test, CALAMARES_TEST_DISK is not set. It should point to a disk which can be safely formatted", + 0 ); } - QVERIFY( KPMHelpers::initKPMcore() ); + kpmcore = new CalamaresUtils::Partition::KPMManager(); FileSystemFactory::init(); refreshDevice(); } +void +PartitionJobTests::cleanupTestCase() +{ + delete kpmcore; +} + void PartitionJobTests::refreshDevice() { QString devicePath = qgetenv( "CALAMARES_TEST_DISK" ); - CoreBackend* backend = CoreBackendManager::self()->backend(); - m_device.reset( backend->scanDevice( devicePath ) ); + m_device.reset( kpmcore->backend()->scanDevice( devicePath ) ); QVERIFY( !m_device.isNull() ); } @@ -206,7 +221,7 @@ PartitionJobTests::testPartitionTable() } void -PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type) +PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type ) { auto job = new CreatePartitionTableJob( m_device.data(), type ); job->updatePreview(); @@ -214,7 +229,10 @@ PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type) } CreatePartitionJob* -PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole role, FileSystem::Type type, qint64 size ) +PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, + PartitionRole role, + FileSystem::Type type, + qint64 size ) { Q_ASSERT( freeSpacePartition ); @@ -222,25 +240,27 @@ PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, Partiti qint64 lastSector; if ( size > 0 ) + { lastSector = firstSector + size / m_device->logicalSize(); + } else + { lastSector = freeSpacePartition->lastSector(); - FileSystem* fs = FileSystemFactory::create( type, firstSector, lastSector - ,m_device->logicalSize() - ); + } + FileSystem* fs = FileSystemFactory::create( type, firstSector, lastSector, m_device->logicalSize() ); - Partition* partition = new Partition( - freeSpacePartition->parent(), - *m_device, - role, - fs, firstSector, lastSector, - QString() /* path */, - KPM_PARTITION_FLAG(None) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - KPM_PARTITION_FLAG(None) /* activeFlags */, - KPM_PARTITION_STATE(New) - ); + Partition* partition = new Partition( freeSpacePartition->parent(), + *m_device, + role, + fs, + firstSector, + lastSector, + QString() /* path */, + KPM_PARTITION_FLAG( None ) /* availableFlags */, + QString() /* mountPoint */, + false /* mounted */, + KPM_PARTITION_FLAG( None ) /* activeFlags */, + KPM_PARTITION_STATE( New ) ); return new CreatePartitionJob( m_device.data(), partition ); } @@ -253,7 +273,7 @@ PartitionJobTests::testCreatePartition() freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 1_MiB); + job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 1_MiB ); Partition* partition1 = job->partition(); QVERIFY( partition1 ); job->updatePreview(); @@ -261,7 +281,7 @@ PartitionJobTests::testCreatePartition() freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::LinuxSwap, 1_MiB); + job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::LinuxSwap, 1_MiB ); Partition* partition2 = job->partition(); QVERIFY( partition2 ); job->updatePreview(); @@ -269,7 +289,7 @@ PartitionJobTests::testCreatePartition() freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, 1_MiB); + job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, 1_MiB ); Partition* partition3 = job->partition(); QVERIFY( partition3 ); job->updatePreview(); @@ -294,7 +314,7 @@ PartitionJobTests::testCreatePartitionExtended() freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 10_MiB); + job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 10_MiB ); Partition* partition1 = job->partition(); QVERIFY( partition1 ); job->updatePreview(); @@ -302,14 +322,15 @@ PartitionJobTests::testCreatePartitionExtended() freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Extended ), FileSystem::Extended, 10_MiB); + job = newCreatePartitionJob( + freePartition, PartitionRole( PartitionRole::Extended ), FileSystem::Extended, 10_MiB ); job->updatePreview(); m_queue.enqueue( job_ptr( job ) ); Partition* extendedPartition = job->partition(); freePartition = firstFreePartition( extendedPartition ); QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Logical ), FileSystem::Ext4, 0); + job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Logical ), FileSystem::Ext4, 0 ); Partition* partition2 = job->partition(); QVERIFY( partition2 ); job->updatePreview(); @@ -333,10 +354,10 @@ PartitionJobTests::testResizePartition_data() QTest::addColumn< unsigned int >( "newStartMiB" ); QTest::addColumn< unsigned int >( "newSizeMiB" ); - QTest::newRow("grow") << 10 << 50 << 10 << 70; - QTest::newRow("shrink") << 10 << 70 << 10 << 50; - QTest::newRow("moveLeft") << 10 << 50 << 8 << 50; - QTest::newRow("moveRight") << 10 << 50 << 12 << 50; + QTest::newRow( "grow" ) << 10 << 50 << 10 << 70; + QTest::newRow( "shrink" ) << 10 << 70 << 10 << 50; + QTest::newRow( "moveLeft" ) << 10 << 50 << 8 << 50; + QTest::newRow( "moveRight" ) << 10 << 50 << 12 << 50; } void @@ -350,9 +371,9 @@ PartitionJobTests::testResizePartition() const qint64 sectorsPerMiB = 1_MiB / m_device->logicalSize(); qint64 oldFirst = sectorsPerMiB * oldStartMiB; - qint64 oldLast = oldFirst + sectorsPerMiB * oldSizeMiB - 1; + qint64 oldLast = oldFirst + sectorsPerMiB * oldSizeMiB - 1; qint64 newFirst = sectorsPerMiB * newStartMiB; - qint64 newLast = newFirst + sectorsPerMiB * newSizeMiB - 1; + qint64 newLast = newFirst + sectorsPerMiB * newSizeMiB - 1; // Make the test data file smaller than the full size of the partition to // accomodate for the file system overhead @@ -366,15 +387,13 @@ PartitionJobTests::testResizePartition() Partition* freePartition = firstFreePartition( m_device->partitionTable() ); QVERIFY( freePartition ); - Partition* partition = KPMHelpers::createNewPartition( - freePartition->parent(), - *m_device, - PartitionRole( PartitionRole::Primary ), - FileSystem::Ext4, - oldFirst, - oldLast, - KPM_PARTITION_FLAG(None) - ); + Partition* partition = KPMHelpers::createNewPartition( freePartition->parent(), + *m_device, + PartitionRole( PartitionRole::Primary ), + FileSystem::Ext4, + oldFirst, + oldLast, + KPM_PARTITION_FLAG( None ) ); CreatePartitionJob* job = new CreatePartitionJob( m_device.data(), partition ); job->updatePreview(); m_queue.enqueue( job_ptr( job ) ); @@ -386,7 +405,8 @@ PartitionJobTests::testResizePartition() // Write a test file in the partition refreshDevice(); QVERIFY( m_device->partitionTable() ); - Partition* partition = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); + Partition* partition + = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); QVERIFY( partition ); QCOMPARE( partition->firstSector(), oldFirst ); QCOMPARE( partition->lastSector(), oldLast ); @@ -411,7 +431,8 @@ PartitionJobTests::testResizePartition() { refreshDevice(); QVERIFY( m_device->partitionTable() ); - Partition* partition = m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) ); + Partition* partition + = m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) ); QVERIFY( partition ); QCOMPARE( partition->firstSector(), newFirst ); QCOMPARE( partition->lastSector(), newLast ); diff --git a/src/modules/partition/tests/PartitionJobTests.h b/src/modules/partition/tests/PartitionJobTests.h index 62d5924ea..1aad945e5 100644 --- a/src/modules/partition/tests/PartitionJobTests.h +++ b/src/modules/partition/tests/PartitionJobTests.h @@ -59,6 +59,7 @@ public: private Q_SLOTS: void initTestCase(); + void cleanupTestCase(); void testPartitionTable(); void testCreatePartition(); void testCreatePartitionExtended(); @@ -71,7 +72,8 @@ private: QueueRunner m_runner; void queuePartitionTableCreation( PartitionTable::TableType type ); - CreatePartitionJob* newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size ); + CreatePartitionJob* + newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size ); void refreshDevice(); }; diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index 2c523b8f7..d3a7198e9 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -32,6 +32,7 @@ import sys import tempfile from libcalamares import * +from libcalamares.utils import mount import gettext _ = gettext.translation("calamares-python", @@ -277,34 +278,29 @@ class UnpackOperation: def mount_image(self, entry, imgmountdir): """ - Mount given image as loop device. + Mount given @p entry as loop device on @p imgmountdir. A *file* entry (e.g. one with *sourcefs* set to *file*) is not mounted and just ignored. - :param entry: - :param imgmountdir: + :param entry: the entry to mount (source is the important property) + :param imgmountdir: where to mount it + + :returns: None, but throws if the mount failed """ if entry.is_file(): return if os.path.isdir(entry.source): - subprocess.check_call(["mount", - "--bind", entry.source, - imgmountdir]) + r = mount(entry.source, imgmountdir, "", "--bind") elif os.path.isfile(entry.source): - subprocess.check_call(["mount", - entry.source, - imgmountdir, - "-t", entry.sourcefs, - "-o", "loop" - ]) + r = mount(entry.source, imgmountdir, entry.sourcefs, "loop") else: # entry.source is a device - subprocess.check_call(["mount", - entry.source, - imgmountdir, - "-t", entry.sourcefs - ]) + r = mount(entry.source, imgmountdir, entry.sourcefs, "") + + if r != 0: + raise subprocess.CalledProcessError(r, "mount") + def unpack_image(self, entry, imgmountdir): """