Merge branch 'kpmcore-manager'

This commit is contained in:
Adriaan de Groot 2020-02-20 22:03:45 +01:00
commit 6d0f5e4111
85 changed files with 2094 additions and 1063 deletions

View File

@ -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()

View File

@ -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
#
#

View File

@ -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();
}

View File

@ -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,7 +64,7 @@ mount( const std::string& device_path,
const std::string& filesystem_name,
const std::string& options )
{
return CalamaresUtils::System::instance()->mount( QString::fromStdString( device_path ),
return CalamaresUtils::Partition::mount( QString::fromStdString( device_path ),
QString::fromStdString( mount_point ),
QString::fromStdString( filesystem_name ),
QString::fromStdString( options ) );

View File

@ -0,0 +1,74 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2018-2019 Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "FileSystem.h"
#include <QObject>
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

View File

@ -0,0 +1,65 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* NOTE: this functionality is only available when Calamares is compiled
* with KPMcore support.
*/
#ifndef PARTITION_FILESYSTEM_H
#define PARTITION_FILESYSTEM_H
#include <kpmcore/fs/filesystem.h>
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

View File

@ -0,0 +1,128 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "KPMManager.h"
#include "utils/Logger.h"
#include <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
#if defined( WITH_KPMCORE4API )
#include <kpmcore/util/externalcommand.h>
#endif
#include <QObject>
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

View File

@ -0,0 +1,69 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* NOTE: this functionality is only available when Calamares is compiled
* with KPMcore support.
*/
#ifndef PARTITION_KPMMANAGER_H
#define PARTITION_KPMMANAGER_H
#include <memory>
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

View File

@ -0,0 +1,132 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
* Copyright 2017-2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "Mount.h"
#include "partition/Sync.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include <QDir>
#include <QTemporaryDir>
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

View File

@ -0,0 +1,80 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
* Copyright 2017-2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef PARTITION_MOUNT_H
#define PARTITION_MOUNT_H
#include "DllMacro.h"
#include <QString>
#include <QStringList>
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

View File

@ -2,7 +2,7 @@
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015, Teo Mrnjavac <teo@kde.org>
* Copyright 2017, Adriaan de Groot <groot@kde.org>
* Copyright 2017, 2019 Adriaan de Groot <groot@kde.org>
*
* 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 <kpmcore/core/partition.h>
#include <kpmcore/core/partitiontable.h>
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
@ -85,11 +94,14 @@ 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

View File

@ -2,6 +2,7 @@
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015, Teo Mrnjavac <teo@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -0,0 +1,102 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2018-2019 Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "PartitionQuery.h"
#include "PartitionIterator.h"
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
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

View File

@ -0,0 +1,78 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* NOTE: this functionality is only available when Calamares is compiled
* with KPMcore support.
*/
#ifndef PARTITION_PARTITIONQUERY_H
#define PARTITION_PARTITIONQUERY_H
#include <QList>
#include <functional>
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

View File

@ -0,0 +1,36 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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 ) );
}

View File

@ -0,0 +1,46 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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,

View File

@ -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

View File

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 );
}

View File

@ -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")
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)" )

View File

@ -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 <QProcess>
#include <QDateTime>
#include <QThread>
@ -29,17 +37,7 @@
#include <kpmcore/ops/resizeoperation.h>
#include <kpmcore/util/report.h>
#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" ),

View File

@ -24,6 +24,7 @@
#include <CppJob.h>
#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<Device*, Partition*>;
/** @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 );

View File

@ -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 ) );

View File

@ -32,7 +32,7 @@ private Q_SLOTS:
void initTestCase();
void cleanup();
void testCreateHostFile();
// TODO: this doesn't actually test any of the functionality of this job
void testCreateTargetFile();
};

View File

@ -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

View File

@ -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 ) );
}
}
@ -96,18 +91,24 @@ BootLoaderModel::updateInternal()
// 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 );
QStandardItem* last = item( rowCount() - 1 );
@ -117,8 +118,10 @@ BootLoaderModel::updateInternal()
if ( !partition )
{
if ( lastIsPartition )
{
takeRow( rowCount() - 1 );
}
}
else
{
QString mountPoint = PartitionInfo::mountPoint( partition );
@ -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 ) );
}
}
@ -151,7 +150,9 @@ BootLoaderModel::data( const QModelIndex& index, int role ) const
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 );
}
@ -167,11 +168,15 @@ findBootloader( const QAbstractItemModel* model, const QString& path )
{
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;
}
@ -201,4 +206,4 @@ restoreSelectedBootLoader( QComboBox& combo, const QString& path )
}
}
} // namespace
} // namespace Calamares

View File

@ -79,5 +79,5 @@ namespace Calamares
* row and sets that as the current row.
*/
void restoreSelectedBootLoader( QComboBox& combo, const QString& path );
} // namespace
} // namespace Calamares
#endif /* BOOTLOADERMODEL_H */

View File

@ -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,19 +33,21 @@
#include <QColor>
#include <QMap>
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 ] =
{
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 ] =
{
static const QColor NEW_PARTITION_COLORS[ NUM_NEW_PARTITION_COLORS ] = {
"#c0392b", //Dark Icon Red
"#f39c1f", //Dark Icon Yellow
"#f1b7bc", //Light Salmon
@ -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,25 +95,32 @@ 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
// free space: we don't want a partition to change colors if space before
@ -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,18 +179,18 @@ 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

View File

@ -53,6 +53,6 @@ QColor colorForPartitionInFreeSpace( Partition* freeSpacePartition );
*/
void invalidateCache();
}
} // namespace ColorUtils
#endif /* COLORUTILS_H */

View File

@ -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 <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <utils/Logger.h>
#include <JobQueue.h>
#include <GlobalStorage.h>
#include <QProcess>
#include <QTemporaryDir>
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,19 +71,24 @@ 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;
}
@ -103,12 +111,13 @@ 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 );
CoreBackend* backend = CoreBackendManager::self()->backend();
#ifdef WITH_KPMCORE331API
#if defined( WITH_KPMCORE4API )
DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) );
#else
DeviceList devices = backend->scanDevices( /* excludeReadOnly */ true );
@ -129,12 +138,10 @@ QList< Device* > getDevices( DeviceType which, qint64 minimumSize )
cDebug() << Logger::SubEntry << "Skipping nullptr device";
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 ) )
{
@ -152,7 +159,9 @@ QList< Device* > getDevices( DeviceType which, qint64 minimumSize )
it = erase( devices, it );
}
else
{
++it;
}
#endif
return devices;

View File

@ -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

View File

@ -30,8 +30,8 @@
// KF5
#include <KFormat>
#include <QStandardItemModel>
#include <QIcon>
#include <QStandardItemModel>
// STL
#include <algorithm>
@ -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,7 +82,9 @@ 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 )
@ -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,
return CalamaresUtils::defaultPixmap(
CalamaresUtils::PartitionDisk,
CalamaresUtils::Original,
QSize( CalamaresUtils::defaultIconSize().width() * 3,
CalamaresUtils::defaultIconSize().height() * 3 ) );
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;

View File

@ -20,8 +20,8 @@
#define DEVICEMODEL_H
#include <QAbstractListModel>
#include <QScopedPointer>
#include <QList>
#include <QScopedPointer>
class Device;
class PartitionModel;

View File

@ -21,91 +21,32 @@
#include "core/KPMHelpers.h"
#include "core/PartitionInfo.h"
#include "core/PartitionIterator.h"
#include "partition/PartitionIterator.h"
#include "utils/Logger.h"
// KPMcore
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystemfactory.h>
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/fs/luks.h>
#include "utils/Logger.h"
#include <QDebug>
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;
return nullptr;
}
@ -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,
FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector, device.logicalSize() );
return new Partition( parent,
device,
role,
fs, fs->firstSector(), fs->lastSector(),
fs,
fs->firstSector(),
fs->lastSector(),
QString() /* path */,
KPM_PARTITION_FLAG( None ) /* availableFlags */,
QString() /* mountPoint */,
false /* mounted */,
flags /* activeFlags */,
KPM_PARTITION_STATE(New)
);
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,7 +104,9 @@ 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 */,
QString() /* mountPoint */,
@ -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

View File

@ -34,7 +34,7 @@ class Partition;
class PartitionNode;
class PartitionRole;
#ifdef WITH_KPMCORE331API
#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
@ -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 */

View File

@ -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 <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <utils/CalamaresUtilsSystem.h>
#include <utils/Logger.h>
#include <JobQueue.h>
#include <GlobalStorage.h>
#include <QProcess>
#include <QTemporaryDir>
using CalamaresUtils::Partition::isPartitionFreeSpace;
using CalamaresUtils::Partition::isPartitionNew;
namespace PartUtils
{
@ -47,13 +52,21 @@ 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 );
@ -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.";
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;
}
}
@ -186,8 +198,8 @@ canBeResized( Partition* candidate )
deb << Logger::Continuation << "Required storage B:" << advisedStorageB
<< QString( "(%1GiB)" ).arg( advisedStorageGiB );
deb << Logger::Continuation << "Available storage B:" << availableStorageB
<< QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) )
<< "for" << convenienceName( candidate ) << "length:" << candidate->length()
<< 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 );
@ -224,64 +236,67 @@ lookForFstabEntries( const QString& partitionPath )
{
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 )
{
@ -329,13 +344,18 @@ findPartitionPathForMountPoint( const FstabEntryList& fstab,
{
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
{
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,7 +450,9 @@ 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;
@ -439,12 +464,14 @@ isEfiBootable( const Partition* candidate )
// Strange case: no root found, no partition table node?
if ( !root )
{
return false;
}
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) );
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;
}
}
@ -481,7 +514,9 @@ findFS( QString fsName, FileSystem::Type* fsType )
fsName = QStringLiteral( "ext4" );
// fsType can be used to check whether fsName was a valid filesystem.
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< int >( t ), FileSystem::nameForType( t, fsLanguage ) );
}
}
#endif
return fsName;
}
} // nmamespace PartUtils
} // namespace PartUtils
/* Implementation of methods for FstabEntry, from OsproberEntry.h */
@ -518,7 +555,8 @@ FstabEntry::fromEtcFstab( const QString& rawLine )
if ( splitLine.length() != 6 )
return FstabEntry { QString(), QString(), QString(), QString(), 0, 0 };
return FstabEntry{ splitLine.at( 0 ), // path, or UUID, or LABEL, etc.
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

View File

@ -22,8 +22,8 @@
#define PARTUTILS_H
#include "OsproberEntry.h"
#include "utils/Units.h"
#include "utils/NamedSuffix.h"
#include "utils/Units.h"
// KPMcore
#include <kpmcore/fs/filesystem.h>
@ -99,6 +99,6 @@ bool isEfiBootable( const Partition* candidate );
*/
QString findFS( QString fsName, FileSystem::Type* fsType );
}
} // namespace PartUtils
#endif // PARTUTILS_H

View File

@ -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(),
Partition* efiPartition = KPMHelpers::createNewPartition( dev->partitionTable(),
*dev,
PartitionRole( PartitionRole::Primary ),
FileSystem::Fat32,
firstFreeSector,
lastSector,
KPM_PARTITION_FLAG(None)
);
KPM_PARTITION_FLAG( None ) );
PartitionInfo::setFormat( efiPartition, true );
PartitionInfo::setMountPoint( efiPartition, o.efiPartitionMountPoint );
core->createPartition( dev, efiPartition, KPM_PARTITION_FLAG_ESP );
@ -177,28 +189,24 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
Partition* swapPartition = nullptr;
if ( o.luksPassphrase.isEmpty() )
{
swapPartition = KPMHelpers::createNewPartition(
dev->partitionTable(),
swapPartition = KPMHelpers::createNewPartition( dev->partitionTable(),
*dev,
PartitionRole( PartitionRole::Primary ),
FileSystem::LinuxSwap,
lastSectorForRoot + 1,
dev->totalLogical() - 1,
KPM_PARTITION_FLAG(None)
);
KPM_PARTITION_FLAG( None ) );
}
else
{
swapPartition = KPMHelpers::createNewEncryptedPartition(
dev->partitionTable(),
swapPartition = KPMHelpers::createNewEncryptedPartition( dev->partitionTable(),
*dev,
PartitionRole( PartitionRole::Primary ),
FileSystem::LinuxSwap,
lastSectorForRoot + 1,
dev->totalLogical() - 1,
o.luksPassphrase,
KPM_PARTITION_FLAG(None)
);
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,15 +243,19 @@ doReplacePartition( PartitionCoreModule* core,
{
Partition* parent = dynamic_cast< Partition* >( partition->parent() );
if ( parent && parent->roles().has( PartitionRole::Extended ) )
{
newRoles = PartitionRole( PartitionRole::Logical );
}
}
}
// Save the first and last sector values as the partition will be deleted
firstSector = partition->firstSector();
lastSector = partition->lastSector();
if ( !partition->roles().has( PartitionRole::Unallocated ) )
{
core->deletePartition( dev, partition );
}
core->layoutApply( dev, firstSector, lastSector, o.luksPassphrase );
@ -254,13 +267,11 @@ namespace Choices
static const NamedEnumTable< SwapChoice >&
nameTable()
{
static const NamedEnumTable<SwapChoice> names{
{ QStringLiteral( "none" ), SwapChoice::NoSwap },
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 }
};
{ QStringLiteral( "file" ), SwapChoice::SwapFile } };
return names;
}

View File

@ -64,7 +64,11 @@ namespace Choices
quint64 requiredSpaceB; // estimated required space for root partition
SwapChoice swap;
AutoPartitionOptions( const QString& fs, const QString& luks, const QString& efi, qint64 requiredBytes, SwapChoice s )
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 )
@ -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.

View File

@ -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,31 +44,35 @@
#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 <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/lvmdevice.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/core/volumemanagerdevice.h>
#include <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/fs/filesystemfactory.h>
#include <kpmcore/fs/luks.h>
#include <kpmcore/fs/lvm2_pv.h>
// Qt
#include <QStandardItemModel>
#include <QDir>
#include <QProcess>
#include <QFutureWatcher>
#include <QProcess>
#include <QStandardItemModel>
#include <QtConcurrent/QtConcurrent>
using CalamaresUtils::Partition::isPartitionFreeSpace;
using CalamaresUtils::Partition::isPartitionNew;
using CalamaresUtils::Partition::PartitionIterator;
PartitionCoreModule::RefreshHelper::RefreshHelper( PartitionCoreModule* module )
: m_module( module )
@ -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,9 +152,11 @@ 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" );
}
}
void
@ -194,22 +204,26 @@ 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;
@ -220,7 +234,9 @@ PartitionCoreModule::doInit()
continue;
}
else
{
bootLoaderDevices.append( *it );
}
m_bootLoaderModel->init( bootLoaderDevices );
@ -229,8 +245,10 @@ 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 );
@ -310,13 +328,13 @@ 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( '_' );
}
CreateVolumeGroupJob* job = new CreateVolumeGroupJob( vgName, pvList, peSize );
job->updatePreview();
@ -324,7 +342,9 @@ PartitionCoreModule::createVolumeGroup( QString &vgName,
LvmDevice* device = new LvmDevice( vgName );
for ( const Partition* p : pvList )
{
device->physicalVolumes() << p;
}
DeviceInfo* deviceInfo = new DeviceInfo( device );
@ -395,12 +415,16 @@ 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 ) )
@ -410,14 +434,17 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition )
{
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;
} );
@ -446,10 +473,14 @@ 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();
jobs << Calamares::job_ptr( job );
@ -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,8 +544,10 @@ 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 )
{
@ -578,9 +606,11 @@ PartitionCoreModule::dumpQueue() const
{
cDebug() << "## Device:" << info->device->name();
for ( auto job : info->jobs )
{
cDebug() << "-" << job->prettyName();
}
}
}
const OsproberEntryList
@ -612,17 +642,22 @@ 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
PartitionCoreModule::updateIsDirty()
@ -636,8 +671,10 @@ PartitionCoreModule::updateIsDirty()
break;
}
if ( oldValue != m_isDirty )
{
isDirtyChanged( m_isDirty );
}
}
void
PartitionCoreModule::scanForEfiSystemPartitions()
@ -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;
}
@ -672,7 +710,9 @@ PartitionCoreModule::scanForLVMPVs()
for ( DeviceInfo* deviceInfo : m_deviceInfos )
{
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< LvmDevice* >( deviceInfo->device.data() );
@ -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();
@ -719,24 +754,30 @@ PartitionCoreModule::scanForLVMPVs()
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< 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< const FS::luks* >( &p->fileSystem() )->innerFS();
if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV )
{
m_lvmPVs << p;
}
}
#endif
}
}
@ -746,14 +787,17 @@ 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,8 +809,10 @@ 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;
}
@ -798,8 +844,8 @@ 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.";
@ -809,30 +855,40 @@ PartitionCoreModule::initLayout( const QVariantList& config )
}
if ( pentry.contains( "size" ) && CalamaresUtils::getString( pentry, "size" ).isEmpty() )
{
sizeString.setNum( CalamaresUtils::getInteger( pentry, "size", 0 ) );
}
else
{
sizeString = CalamaresUtils::getString( pentry, "size" );
}
if ( pentry.contains( "minSize" ) && CalamaresUtils::getString( pentry, "minSize" ).isEmpty() )
{
minSizeString.setNum( CalamaresUtils::getInteger( pentry, "minSize", 0 ) );
}
else
{
minSizeString = CalamaresUtils::getString( pentry, "minSize" );
}
if ( pentry.contains( "maxSize" ) && CalamaresUtils::getString( pentry, "maxSize" ).isEmpty() )
{
maxSizeString.setNum( CalamaresUtils::getInteger( pentry, "maxSize", 0 ) );
}
else
{
maxSizeString = CalamaresUtils::getString( pentry, "maxSize" );
}
if ( !m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ),
CalamaresUtils::getString( pentry, "mountPoint" ),
CalamaresUtils::getString( pentry, "filesystem" ),
sizeString,
minSizeString,
maxSizeString
) )
maxSizeString ) )
{
cError() << "Partition layout entry #" << config.indexOf(r)
<< "is invalid, switching to default layout.";
cError() << "Partition layout entry #" << config.indexOf( r ) << "is invalid, switching to default layout.";
delete ( m_partLayout );
initLayout();
break;
@ -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 )
{
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
@ -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();
}
@ -995,7 +1050,9 @@ 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();

View File

@ -26,6 +26,7 @@
#include "core/PartitionModel.h"
#include "Job.h"
#include "partition/KPMManager.h"
// KPMcore
#include <kpmcore/core/lvmdevice.h>
@ -138,8 +139,8 @@ 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 );
@ -166,7 +167,12 @@ public:
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,
PartitionNode* parent,
const PartitionRole& role );
/**
* @brief jobs creates and returns a list of jobs which can then apply the changes
@ -235,6 +241,8 @@ Q_SIGNALS:
void deviceReverted( Device* device );
private:
CalamaresUtils::Partition::KPMManager m_kpmcore;
void refreshAfterModelChange();
/**

View File

@ -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< 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();
}
} // namespace
return !mountPoint( partition ).isEmpty() || format( partition ) || flags( partition ) != partition->activeFlags();
}
} // namespace PartitionInfo

View File

@ -60,6 +60,6 @@ void reset( Partition* partition );
*/
bool isDirty( Partition* partition );
};
}; // namespace PartitionInfo
#endif /* PARTITIONINFO_H */

View File

@ -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 <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
@ -44,8 +44,10 @@ getDefaultFileSystemType()
{
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 )
{
@ -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 );

View File

@ -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;

View File

@ -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 <QColor>
using CalamaresUtils::Partition::isPartitionFreeSpace;
using CalamaresUtils::Partition::isPartitionNew;
//- ResetHelper --------------------------------------------
PartitionModel::ResetHelper::ResetHelper( PartitionModel* model )
: m_model( model )
@ -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 ) )
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,25 +190,30 @@ 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 );
@ -189,15 +221,17 @@ PartitionModel::data( const QModelIndex& index, int role ) const
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,38 +246,43 @@ 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.
@ -256,7 +295,9 @@ QVariant
PartitionModel::headerData( int section, Qt::Orientation, int role ) const
{
if ( role != Qt::DisplayRole )
{
return QVariant();
}
switch ( section )
{
@ -279,7 +320,9 @@ PartitionModel::partitionForIndex( const QModelIndex& index ) const
{
QMutexLocker lock( &m_lock );
if ( !index.isValid() )
{
return nullptr;
}
return reinterpret_cast< Partition* >( index.internalPointer() );
}

View File

@ -61,6 +61,7 @@ public:
ResetHelper( const ResetHelper& ) = delete;
ResetHelper& operator=( const ResetHelper& ) = delete;
private:
PartitionModel* m_model;
};
@ -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();

View File

@ -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 <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
@ -65,6 +66,9 @@
#include <QtConcurrent/QtConcurrent>
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 )

View File

@ -20,7 +20,8 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/fs/filesystemfactory.h>
#include <kpmcore/fs/luks.h>
// Qt
#include <QComboBox>
#include <QDir>
#include <QListWidgetItem>
@ -51,6 +50,9 @@
#include <QRegularExpressionValidator>
#include <QSet>
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 );

View File

@ -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 <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystemfactory.h>
// Qt
#include <QComboBox>
#include <QDir>
#include <QPushButton>
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

View File

@ -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 <kpmcore/core/device.h>
@ -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();

View File

@ -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 <kpmcore/core/device.h>
@ -33,6 +35,8 @@
#include <QMouseEvent>
#include <QStyleOption>
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,
{}

View File

@ -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.

View File

@ -35,6 +35,7 @@ class ChoicePage;
class PartitionPage;
class PartitionCoreModule;
class QStackedWidget;
class WaitingWidget;
template<typename T> class QFutureWatcher;
@ -82,7 +83,7 @@ private:
ChoicePage* m_choicePage;
PartitionPage* m_manualPartitionPage;
QWidget* m_waitingWidget;
WaitingWidget* m_waitingWidget;
QFutureWatcher<void>* m_future;
QSet< PartitionActions::Choices::SwapChoice > m_swapChoices;

View File

@ -2,7 +2,7 @@
*
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
* Copyright 2019-2020, Adriaan de Groot <groot@kde.org>
*
* 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 <QComboBox>
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 )
{

View File

@ -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 <QProcess>
#include <QStringList>
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

View File

@ -19,7 +19,7 @@
#ifndef CLEARMOUNTSJOB_H
#define CLEARMOUNTSJOB_H
#include <Job.h>
#include "Job.h"
class Device;

View File

@ -19,7 +19,7 @@
#ifndef CLEARTEMPMOUNTSJOB_H
#define CLEARTEMPMOUNTSJOB_H
#include <Job.h>
#include "Job.h"
class Device;

View File

@ -18,14 +18,12 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <kpmcore/core/device.h>
#include <kpmcore/core/lvmdevice.h>
#include <kpmcore/core/partition.h>
@ -34,8 +32,8 @@
#include <kpmcore/ops/newoperation.h>
#include <kpmcore/util/report.h>
using KPMHelpers::untranslatedFS;
using KPMHelpers::userVisibleFS;
using CalamaresUtils::Partition::untranslatedFS;
using CalamaresUtils::Partition::userVisibleFS;
CreatePartitionJob::CreatePartitionJob( Device* device, Partition* partition )
: PartitionJob( partition )

View File

@ -20,7 +20,7 @@
#ifndef CREATEPARTITIONJOB_H
#define CREATEPARTITIONJOB_H
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
class Device;
class Partition;

View File

@ -20,21 +20,22 @@
#include "jobs/CreatePartitionTableJob.h"
#include "core/PartitionIterator.h"
#include "partition/PartitionIterator.h"
#include "utils/Logger.h"
// KPMcore
#include <core/device.h>
#include <core/partition.h>
#include <core/partitiontable.h>
#include <fs/filesystem.h>
#include <ops/createpartitiontableoperation.h>
#include <util/report.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/core/partitiontable.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/ops/createpartitiontableoperation.h>
#include <kpmcore/util/report.h>
// Qt
#include <QProcess>
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();

View File

@ -20,7 +20,8 @@
#ifndef CREATEPARTITIONTABLEJOB_H
#define CREATEPARTITIONTABLEJOB_H
#include <Job.h>
#include "Job.h"
#include "partition/KPMManager.h"
// KPMcore
#include <kpmcore/core/partitiontable.h>
@ -50,6 +51,7 @@ public:
}
private:
CalamaresUtils::Partition::KPMManager m_kpmcore;
Device* m_device;
PartitionTable::TableType m_type;
PartitionTable* createTable();

View File

@ -19,12 +19,13 @@
#ifndef CREATEVOLUMEGROUPJOB_H
#define CREATEVOLUMEGROUPJOB_H
#include <Job.h>
#include <kpmcore/core/partition.h>
#include "Job.h"
#include "partition/KPMManager.h"
#include <QVector>
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;

View File

@ -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;
};

View File

@ -21,12 +21,12 @@
#include "jobs/DeletePartitionJob.h"
// KPMcore
#include <core/device.h>
#include <core/partition.h>
#include <core/partitiontable.h>
#include <fs/filesystem.h>
#include <ops/deleteoperation.h>
#include <util/report.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/core/partitiontable.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/ops/deleteoperation.h>
#include <kpmcore/util/report.h>
DeletePartitionJob::DeletePartitionJob( Device* device, Partition* partition )
: PartitionJob( partition )

View File

@ -20,7 +20,7 @@
#ifndef DELETEPARTITIONJOB_H
#define DELETEPARTITIONJOB_H
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
class Device;
class Partition;

View File

@ -18,31 +18,31 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <core/device.h>
#include <core/partition.h>
#include <fs/filesystem.h>
#include <fs/luks.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/fs/luks.h>
// Qt
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QProcess>
using KPMHelpers::untranslatedFS;
using KPMHelpers::userVisibleFS;
using CalamaresUtils::Partition::untranslatedFS;
using CalamaresUtils::Partition::userVisibleFS;
using CalamaresUtils::Partition::PartitionIterator;
typedef QHash< QString, QString > UuidForPartitionHash;

View File

@ -20,7 +20,7 @@
#ifndef FILLGLOBALSTORAGEJOB_H
#define FILLGLOBALSTORAGEJOB_H
#include <Job.h>
#include "Job.h"
// Qt
#include <QList>

View File

@ -2,6 +2,7 @@
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "jobs/FormatPartitionJob.h"
#include "core/KPMHelpers.h"
#include "FormatPartitionJob.h"
#include "partition/FileSystem.h"
#include "utils/Logger.h"
// KPMcore
#include <core/device.h>
#include <core/partition.h>
#include <core/partitiontable.h>
#include <fs/filesystem.h>
#include <ops/createfilesystemoperation.h>
#include <util/report.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/core/partitiontable.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/ops/createfilesystemoperation.h>
#include <kpmcore/util/report.h>
using KPMHelpers::untranslatedFS;
using KPMHelpers::userVisibleFS;
using CalamaresUtils::Partition::untranslatedFS;
using CalamaresUtils::Partition::userVisibleFS;
FormatPartitionJob::FormatPartitionJob( Device* device, Partition* partition )
: PartitionJob( partition )

View File

@ -20,7 +20,7 @@
#ifndef FORMATPARTITIONJOB_H
#define FORMATPARTITIONJOB_H
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
class Device;
class Partition;

View File

@ -16,7 +16,7 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
PartitionJob::PartitionJob( Partition* partition )
: m_partition( partition )

View File

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <Job.h>
#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;
};

View File

@ -19,7 +19,8 @@
#ifndef REMOVEVOLUMEGROUPJOB_H
#define REMOVEVOLUMEGROUPJOB_H
#include <Job.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;
};

View File

@ -23,9 +23,9 @@
#include "utils/Units.h"
// KPMcore
#include <core/device.h>
#include <ops/resizeoperation.h>
#include <util/report.h>
#include <kpmcore/core/device.h>
#include <kpmcore/ops/resizeoperation.h>
#include <kpmcore/util/report.h>
using CalamaresUtils::BytesToMiB;

View File

@ -20,7 +20,7 @@
#ifndef RESIZEPARTITIONJOB_H
#define RESIZEPARTITIONJOB_H
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
class Device;
class Partition;

View File

@ -19,7 +19,8 @@
#ifndef RESIZEVOLUMEGROUPJOB_H
#define RESIZEVOLUMEGROUPJOB_H
#include <Job.h>
#include "Job.h"
#include "partition/KPMManager.h"
#include <QVector>
@ -42,6 +43,7 @@ private:
QString targetPartitions() const;
private:
CalamaresUtils::Partition::KPMManager m_kpmcore;
LvmDevice* m_device;
QVector< const Partition* > m_partitionList;
};

View File

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* Based on the SetPartFlagsJob class from KDE Partition Manager,
* Copyright 2008, 2010, Volker Lanz <vl@fidra.de>
@ -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 <core/device.h>
#include <core/partition.h>
#include <fs/filesystem.h>
#include <ops/setpartflagsoperation.h>
#include <util/report.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/ops/setpartflagsoperation.h>
#include <kpmcore/util/report.h>
using CalamaresUtils::BytesToMiB;
using KPMHelpers::untranslatedFS;
using KPMHelpers::userVisibleFS;
using CalamaresUtils::Partition::untranslatedFS;
using CalamaresUtils::Partition::userVisibleFS;
SetPartFlagsJob::SetPartFlagsJob( Device* device,
Partition* partition,

View File

@ -22,7 +22,7 @@
#ifndef SETPARTITIONFLAGSJOB_H
#define SETPARTITIONFLAGSJOB_H
#include <jobs/PartitionJob.h>
#include "PartitionJob.h"
#include <kpmcore/core/partitiontable.h>

View File

@ -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}
)

View File

@ -0,0 +1,66 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "ClearMountsJobTests.h"
#include "utils/Logger.h"
#include <QtTest/QtTest>
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 );
}

View File

@ -0,0 +1,34 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef CLEARMOUNTSJOBTESTS_H
#define CLEARMOUNTSJOBTESTS_H
#include <QObject>
class ClearMountsJobTests : public QObject
{
Q_OBJECT
public:
ClearMountsJobTests();
private Q_SLOTS:
void testFindPartitions();
};
#endif

View File

@ -19,16 +19,18 @@
#include <PartitionJobTests.h>
#include "partition/KPMManager.h"
#include "partition/PartitionQuery.h"
#include "utils/Logger.h"
#include "utils/Units.h"
#include <core/KPMHelpers.h>
#include <jobs/CreatePartitionJob.h>
#include <jobs/CreatePartitionTableJob.h>
#include <jobs/ResizePartitionJob.h>
#include <core/KPMHelpers.h>
// CalaPM
#include <backend/corebackend.h>
#include <backend/corebackendmanager.h>
#include <fs/filesystemfactory.h>
// 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;
@ -115,8 +117,10 @@ static Partition*
firstFreePartition( PartitionNode* parent )
{
for ( auto child : parent->children() )
if ( KPMHelpers::isPartitionFreeSpace( child ) )
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() );
}
@ -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(),
Partition* partition = new Partition( freeSpacePartition->parent(),
*m_device,
role,
fs, firstSector, lastSector,
fs,
firstSector,
lastSector,
QString() /* path */,
KPM_PARTITION_FLAG( None ) /* availableFlags */,
QString() /* mountPoint */,
false /* mounted */,
KPM_PARTITION_FLAG( None ) /* activeFlags */,
KPM_PARTITION_STATE(New)
);
KPM_PARTITION_STATE( New ) );
return new CreatePartitionJob( m_device.data(), partition );
}
@ -302,7 +322,8 @@ 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();
@ -366,15 +387,13 @@ PartitionJobTests::testResizePartition()
Partition* freePartition = firstFreePartition( m_device->partitionTable() );
QVERIFY( freePartition );
Partition* partition = KPMHelpers::createNewPartition(
freePartition->parent(),
Partition* partition = KPMHelpers::createNewPartition( freePartition->parent(),
*m_device,
PartitionRole( PartitionRole::Primary ),
FileSystem::Ext4,
oldFirst,
oldLast,
KPM_PARTITION_FLAG(None)
);
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 );

View File

@ -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();
};

View File

@ -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):
"""