74ead4c7ba
Due to changes to the FileSsytem::typeForName() function, more processing is needed to deal with locales and different cases. This is done by refactoring the findFS() function, initially located in the PartitionViewStep class, and making it available to the whole module. Additionnally, more checks have been implemented regarding the use of global storage in the PartitionLayout class, and the filesystem types now use the correct FileSystem::Type, as requested. Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
254 lines
7.6 KiB
C++
254 lines
7.6 KiB
C++
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
|
*
|
|
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
|
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
|
* Copyright 2018, Collabora Ltd
|
|
*
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* 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 "GlobalStorage.h"
|
|
#include "JobQueue.h"
|
|
|
|
#include "core/PartitionLayout.h"
|
|
|
|
#include "core/KPMHelpers.h"
|
|
#include "core/PartitionActions.h"
|
|
#include "core/PartitionInfo.h"
|
|
#include "core/PartUtils.h"
|
|
|
|
#include <kpmcore/core/device.h>
|
|
#include <kpmcore/core/partition.h>
|
|
#include <kpmcore/fs/filesystem.h>
|
|
|
|
static FileSystem::Type
|
|
getDefaultFileSystemType()
|
|
{
|
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
|
FileSystem::Type defaultFS = FileSystem::Ext4;
|
|
|
|
if ( gs->contains( "defaultFileSystemType" ) )
|
|
{
|
|
PartUtils::findFS( gs->value( "defaultFileSystemType" ).toString(), &defaultFS);
|
|
if ( defaultFS == FileSystem::Unknown )
|
|
defaultFS = FileSystem::Ext4;
|
|
}
|
|
|
|
return defaultFS;
|
|
}
|
|
|
|
PartitionLayout::PartitionLayout()
|
|
{
|
|
m_defaultFsType = getDefaultFileSystemType();
|
|
}
|
|
|
|
PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry )
|
|
{
|
|
m_defaultFsType = getDefaultFileSystemType();
|
|
m_partLayout.append( entry );
|
|
}
|
|
|
|
PartitionLayout::PartitionLayout( const PartitionLayout& layout )
|
|
: m_partLayout( layout.m_partLayout )
|
|
, m_defaultFsType( layout.m_defaultFsType )
|
|
{
|
|
}
|
|
|
|
PartitionLayout::~PartitionLayout()
|
|
{
|
|
}
|
|
|
|
void
|
|
PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry )
|
|
{
|
|
m_partLayout.append( entry );
|
|
}
|
|
|
|
static double
|
|
parseSizeString( const QString& sizeString, PartitionLayout::SizeUnit* unit )
|
|
{
|
|
double value;
|
|
bool ok;
|
|
QString valueString;
|
|
QString unitString;
|
|
|
|
QRegExp rx( "[KkMmGg%]" );
|
|
int pos = rx.indexIn( sizeString );
|
|
if (pos > 0)
|
|
{
|
|
valueString = sizeString.mid( 0, pos );
|
|
unitString = sizeString.mid( pos );
|
|
}
|
|
else
|
|
valueString = sizeString;
|
|
|
|
value = valueString.toDouble( &ok );
|
|
if ( !ok )
|
|
{
|
|
/*
|
|
* In case the conversion fails, a size of 100% allows a few cases to pass
|
|
* anyway (e.g. when it is the last partition of the layout)
|
|
*/
|
|
*unit = PartitionLayout::SizeUnit::Percent;
|
|
return 100;
|
|
}
|
|
|
|
if ( unitString.length() > 0 )
|
|
{
|
|
if ( unitString.at(0) == '%' )
|
|
*unit = PartitionLayout::SizeUnit::Percent;
|
|
else if ( unitString.at(0).toUpper() == 'K' )
|
|
*unit = PartitionLayout::SizeUnit::KiB;
|
|
else if ( unitString.at(0).toUpper() == 'M' )
|
|
*unit = PartitionLayout::SizeUnit::MiB;
|
|
else if ( unitString.at(0).toUpper() == 'G' )
|
|
*unit = PartitionLayout::SizeUnit::GiB;
|
|
else
|
|
*unit = PartitionLayout::SizeUnit::Byte;
|
|
}
|
|
else
|
|
{
|
|
*unit = PartitionLayout::SizeUnit::Byte;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
PartitionLayout::PartitionEntry::PartitionEntry(const QString& size, const QString& min)
|
|
{
|
|
partSize = parseSizeString( size , &partSizeUnit );
|
|
if ( !min.isEmpty() )
|
|
partMinSize = parseSizeString( min , &partMinSizeUnit );
|
|
}
|
|
|
|
void
|
|
PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const QString& min )
|
|
{
|
|
PartitionLayout::PartitionEntry entry( size, min );
|
|
|
|
entry.partMountPoint = mountPoint;
|
|
entry.partFileSystem = m_defaultFsType;
|
|
|
|
m_partLayout.append( entry );
|
|
}
|
|
|
|
void
|
|
PartitionLayout::addEntry( const QString& label, const QString& mountPoint, const QString& fs, const QString& size, const QString& min )
|
|
{
|
|
PartitionLayout::PartitionEntry entry( size, min );
|
|
|
|
entry.partLabel = label;
|
|
entry.partMountPoint = mountPoint;
|
|
PartUtils::findFS( fs, &entry.partFileSystem );
|
|
if ( entry.partFileSystem == FileSystem::Unknown )
|
|
entry.partFileSystem = m_defaultFsType;
|
|
|
|
m_partLayout.append( entry );
|
|
}
|
|
|
|
static qint64
|
|
sizeToSectors( double size, PartitionLayout::SizeUnit unit, qint64 totalSize, qint64 logicalSize )
|
|
{
|
|
qint64 sectors;
|
|
double tmp;
|
|
|
|
if ( unit == PartitionLayout::SizeUnit::Percent )
|
|
{
|
|
tmp = static_cast<double>( totalSize ) * size / 100;
|
|
sectors = static_cast<qint64>( tmp );
|
|
}
|
|
else
|
|
{
|
|
tmp = size;
|
|
if ( unit >= PartitionLayout::SizeUnit::KiB )
|
|
tmp *= 1024;
|
|
if ( unit >= PartitionLayout::SizeUnit::MiB )
|
|
tmp *= 1024;
|
|
if ( unit >= PartitionLayout::SizeUnit::GiB )
|
|
tmp *= 1024;
|
|
|
|
sectors = PartitionActions::bytesToSectors( static_cast<unsigned long long>( tmp ),
|
|
logicalSize
|
|
);
|
|
}
|
|
|
|
return sectors;
|
|
}
|
|
|
|
QList< Partition* >
|
|
PartitionLayout::execute( Device *dev, qint64 firstSector,
|
|
qint64 lastSector, QString luksPassphrase,
|
|
PartitionNode* parent,
|
|
const PartitionRole& role )
|
|
{
|
|
QList< Partition* > partList;
|
|
qint64 size, minSize, end;
|
|
qint64 totalSize = lastSector - firstSector + 1;
|
|
qint64 availableSize = totalSize;
|
|
|
|
// TODO: Refine partition sizes to make sure there is room for every partition
|
|
// Use a default (200-500M ?) minimum size for partition without minSize
|
|
|
|
foreach( const PartitionLayout::PartitionEntry& part, m_partLayout )
|
|
{
|
|
Partition *currentPartition = nullptr;
|
|
|
|
// Calculate partition size
|
|
size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() );
|
|
minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() );
|
|
if ( size < minSize )
|
|
size = minSize;
|
|
if ( size > availableSize )
|
|
size = availableSize;
|
|
end = firstSector + size - 1;
|
|
|
|
if ( luksPassphrase.isEmpty() )
|
|
{
|
|
currentPartition = KPMHelpers::createNewPartition(
|
|
parent,
|
|
*dev,
|
|
role,
|
|
part.partFileSystem,
|
|
firstSector,
|
|
end,
|
|
PartitionTable::FlagNone
|
|
);
|
|
}
|
|
else
|
|
{
|
|
currentPartition = KPMHelpers::createNewEncryptedPartition(
|
|
parent,
|
|
*dev,
|
|
role,
|
|
part.partFileSystem,
|
|
firstSector,
|
|
end,
|
|
luksPassphrase,
|
|
PartitionTable::FlagNone
|
|
);
|
|
}
|
|
PartitionInfo::setFormat( currentPartition, true );
|
|
PartitionInfo::setMountPoint( currentPartition, part.partMountPoint );
|
|
if ( !part.partLabel.isEmpty() )
|
|
currentPartition->fileSystem().setLabel( part.partLabel );
|
|
// Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set.
|
|
// Otherwise they ignore the device in boot-order, so add it here.
|
|
partList.append( currentPartition );
|
|
firstSector = end + 1;
|
|
availableSize -= size;
|
|
}
|
|
|
|
return partList;
|
|
}
|