Merge pull request #2400 from ArrayBolt3/arraybolt3/restrict-fs
Allow restricting the filesystem's usable in manual partitioning
This commit is contained in:
@@ -60,6 +60,7 @@ if(KPMcore_FOUND)
|
||||
core/DeviceList.cpp
|
||||
core/DeviceModel.cpp
|
||||
core/KPMHelpers.cpp
|
||||
core/DirFSRestrictLayout.cpp
|
||||
core/OsproberEntry.cpp
|
||||
core/PartitionActions.cpp
|
||||
core/PartitionCoreModule.cpp
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "gui/PartitionBarsView.h"
|
||||
#include "gui/PartitionLabelsView.h"
|
||||
#include "gui/PartitionPage.h"
|
||||
#include "partition/FileSystem.h"
|
||||
|
||||
#include "Branding.h"
|
||||
#include "GlobalStorage.h"
|
||||
@@ -33,6 +34,7 @@
|
||||
#include "widgets/TranslationFix.h"
|
||||
#include "widgets/WaitingWidget.h"
|
||||
|
||||
#include <kpmcore/core/device.h>
|
||||
#include <kpmcore/core/partition.h>
|
||||
|
||||
#include <QFormLayout>
|
||||
@@ -59,6 +61,18 @@ PartitionViewStep::PartitionViewStep( QObject* parent )
|
||||
// We're not done loading, but we need the configuration map first.
|
||||
}
|
||||
|
||||
PartitionViewStep::FSConflictEntry::FSConflictEntry() {}
|
||||
|
||||
PartitionViewStep::FSConflictEntry::FSConflictEntry( const QString& conflictingPathArg,
|
||||
const QString& conflictingFilesystemArg,
|
||||
const QString& conflictedPathArg,
|
||||
QStringList allowableFilesystemsArg )
|
||||
: conflictingPath( conflictingPathArg )
|
||||
, conflictingFilesystem( conflictingFilesystemArg )
|
||||
, conflictedPath( conflictedPathArg )
|
||||
, allowableFilesystems( allowableFilesystemsArg )
|
||||
{}
|
||||
|
||||
void
|
||||
PartitionViewStep::initPartitionCoreModule()
|
||||
{
|
||||
@@ -459,6 +473,12 @@ PartitionViewStep::onActivate()
|
||||
}
|
||||
}
|
||||
|
||||
static QString
|
||||
listItem( QString s )
|
||||
{
|
||||
return s.prepend( QStringLiteral( "<li>" ) ).append( QStringLiteral( "</li>" ) );
|
||||
}
|
||||
|
||||
static bool
|
||||
shouldWarnForGPTOnBIOS( const PartitionCoreModule* core )
|
||||
{
|
||||
@@ -522,6 +542,143 @@ shouldWarnForNotEncryptedBoot( const Config* config, const PartitionCoreModule*
|
||||
return false;
|
||||
}
|
||||
|
||||
static PartitionViewStep::FSConflictEntry
|
||||
calcFSConflictEntry( PartitionCoreModule* core, PartitionModel* partModel, QModelIndex partFsIdx, QModelIndex partMountPointIdx, QStringList mountPointList )
|
||||
{
|
||||
PartitionViewStep::FSConflictEntry result;
|
||||
|
||||
QString partFs = partModel->data( partFsIdx ).toString().toLower();
|
||||
QString partMountPoint = partModel->data( partMountPointIdx ).toString();
|
||||
FileSystem::Type fsType;
|
||||
PartUtils::canonicalFilesystemName( partFs, &fsType );
|
||||
bool fsTypeIsAllowed = false;
|
||||
if ( fsType == FileSystem::Type::Unknown )
|
||||
{
|
||||
fsTypeIsAllowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QList< FileSystem::Type > allowedFsTypes = core->dirFSRestrictLayout().allowedFSTypes( partMountPoint, mountPointList, true );
|
||||
for ( const auto& allowedFsType : allowedFsTypes )
|
||||
{
|
||||
if ( fsType == allowedFsType )
|
||||
{
|
||||
fsTypeIsAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !fsTypeIsAllowed )
|
||||
{
|
||||
QString conflictedPath = core->dirFSRestrictLayout().diagnoseFSConflict( partMountPoint, fsType, mountPointList );
|
||||
QList< FileSystem::Type > nonConflictingFilesystemTypes = core->dirFSRestrictLayout().allowedFSTypes( conflictedPath, mountPointList, true );
|
||||
QStringList nonConflictingFilesystems;
|
||||
for ( const auto& fsType : nonConflictingFilesystemTypes )
|
||||
{
|
||||
nonConflictingFilesystems.append( Calamares::Partition::prettyNameForFileSystemType( fsType ) );
|
||||
}
|
||||
result = PartitionViewStep::FSConflictEntry( partMountPoint, partFs, conflictedPath, nonConflictingFilesystems );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static QList< PartitionViewStep::FSConflictEntry >
|
||||
checkForFilesystemConflicts( PartitionCoreModule* core )
|
||||
{
|
||||
QList< PartitionViewStep::FSConflictEntry > result;
|
||||
|
||||
DeviceModel* dm = core->deviceModel();
|
||||
QStringList mountPointList;
|
||||
|
||||
// Walk the device and partition tree, extracting mountpoints from it
|
||||
for ( int i = 0; i < dm->rowCount(); i++ )
|
||||
{
|
||||
Device* dev = dm->deviceForIndex( dm->index( i ) );
|
||||
PartitionModel* pm = core->partitionModelForDevice( dev );
|
||||
|
||||
QModelIndex extPartMountPointIdx = QModelIndex();
|
||||
bool extPartFound = false;
|
||||
for ( int j = 0; j < pm->rowCount(); j++ )
|
||||
{
|
||||
QModelIndex partFsIdx = pm->index( j, PartitionModel::FileSystemColumn );
|
||||
QModelIndex partMountPointIdx = pm->index( j, PartitionModel::MountPointColumn );
|
||||
|
||||
if ( pm->data( partFsIdx ).toString().toLower() == "extended" )
|
||||
{
|
||||
extPartFound = true;
|
||||
extPartMountPointIdx = partMountPointIdx;
|
||||
break;
|
||||
}
|
||||
|
||||
QString mountPoint = pm->data( partMountPointIdx ).toString();
|
||||
if ( !mountPoint.isEmpty() )
|
||||
{
|
||||
mountPointList.append( mountPoint );
|
||||
}
|
||||
}
|
||||
if ( extPartFound )
|
||||
{
|
||||
for ( int j = 0; j < pm->rowCount( extPartMountPointIdx ); j++ )
|
||||
{
|
||||
QModelIndex partMountPointIdx = pm->index( j, PartitionModel::MountPointColumn, extPartMountPointIdx );
|
||||
QString mountPoint = pm->data( partMountPointIdx ).toString();
|
||||
if ( !mountPoint.isEmpty() )
|
||||
{
|
||||
mountPointList.append( mountPoint );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the device and partition tree again, validating it this time
|
||||
for ( int i = 0; i < dm->rowCount(); i++ )
|
||||
{
|
||||
Device* dev = dm->deviceForIndex( dm->index( i ) );
|
||||
PartitionModel* pm = core->partitionModelForDevice( dev );
|
||||
|
||||
QModelIndex extPartFsIdx = QModelIndex();
|
||||
QModelIndex extPartMountPointIdx = QModelIndex();
|
||||
bool extPartFound = false;
|
||||
|
||||
for ( int j = 0; j < pm->rowCount(); j++ )
|
||||
{
|
||||
QModelIndex partFsIdx = pm->index( j, PartitionModel::FileSystemColumn );
|
||||
QModelIndex partMountPointIdx = pm->index( j, PartitionModel::MountPointColumn );
|
||||
|
||||
if ( pm->data( partFsIdx ).toString().toLower() == "extended" )
|
||||
{
|
||||
extPartFound = true;
|
||||
extPartFsIdx = partFsIdx;
|
||||
extPartMountPointIdx = partMountPointIdx;
|
||||
break;
|
||||
}
|
||||
|
||||
PartitionViewStep::FSConflictEntry conflictEntry = calcFSConflictEntry( core, pm, partFsIdx, partMountPointIdx, mountPointList );
|
||||
if ( !conflictEntry.conflictedPath.isEmpty() )
|
||||
{
|
||||
result.append( conflictEntry );
|
||||
}
|
||||
}
|
||||
if ( extPartFound )
|
||||
{
|
||||
for ( int j = 0; j < pm->rowCount( extPartFsIdx ); j++ )
|
||||
{
|
||||
QModelIndex partFsIdx = pm->index( j, PartitionModel::FileSystemColumn, extPartFsIdx );
|
||||
QModelIndex partMountPointIdx = pm->index( j, PartitionModel::MountPointColumn, extPartMountPointIdx );
|
||||
PartitionViewStep::FSConflictEntry conflictEntry = calcFSConflictEntry( core, pm, partFsIdx, partMountPointIdx, mountPointList );
|
||||
if ( !conflictEntry.conflictedPath.isEmpty() )
|
||||
{
|
||||
result.append( conflictEntry );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PartitionViewStep::onLeave()
|
||||
{
|
||||
@@ -532,6 +689,10 @@ PartitionViewStep::onLeave()
|
||||
}
|
||||
|
||||
const auto* branding = Calamares::Branding::instance();
|
||||
|
||||
const QString startList = QStringLiteral( "<br/><br/><ul>" );
|
||||
const QString endList = QStringLiteral( "</ul><br/><br/>" );
|
||||
|
||||
if ( m_widget->currentWidget() == m_manualPartitionPage )
|
||||
{
|
||||
if ( PartUtils::isEfiSystem() )
|
||||
@@ -587,12 +748,6 @@ PartitionViewStep::onLeave()
|
||||
const QString possibleFail = tr( "You can continue with this EFI system "
|
||||
"partition configuration but your system may fail to start." );
|
||||
|
||||
const QString startList = QStringLiteral( "<br/><br/><ul>" );
|
||||
const QString endList = QStringLiteral( "</ul><br/><br/>" );
|
||||
|
||||
auto listItem = []( QString s ) -> QString
|
||||
{ return s.prepend( QStringLiteral( "<li>" ) ).append( QStringLiteral( "</li>" ) ); };
|
||||
|
||||
if ( !esp )
|
||||
{
|
||||
cDebug() << o << "No ESP mounted";
|
||||
@@ -684,6 +839,52 @@ PartitionViewStep::onLeave()
|
||||
Calamares::fixButtonLabels( &mb );
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
QList< FSConflictEntry > conflictMap = checkForFilesystemConflicts( m_core );
|
||||
if ( !conflictMap.isEmpty() )
|
||||
{
|
||||
QString message = tr( "Filesystem conflicts found" );
|
||||
const QString descHeader = tr( "The chosen manual partitioning layout does not "
|
||||
"comply with the filesystem restrictions set by the "
|
||||
"distro. The following issues were found:");
|
||||
|
||||
QStringList issueList;
|
||||
for ( const auto& entry : conflictMap )
|
||||
{
|
||||
QString buildString;
|
||||
if ( entry.conflictedPath == "any" )
|
||||
{
|
||||
buildString = tr( "The %1 directory uses filesystem %2, but this distro only allows the following filesystems: %3." )
|
||||
.arg( entry.conflictingPath )
|
||||
.arg( entry.conflictingFilesystem )
|
||||
.arg( entry.allowableFilesystems.join( ", " ) );
|
||||
issueList.append( buildString );
|
||||
}
|
||||
else
|
||||
{
|
||||
buildString = tr( "The %1 directory uses filesystem %2, but the %3 directory must use one of the following filesystems: %4." )
|
||||
.arg( entry.conflictingPath )
|
||||
.arg( entry.conflictingFilesystem )
|
||||
.arg( entry.conflictedPath )
|
||||
.arg( entry.allowableFilesystems.join( ", " ) );
|
||||
issueList.append( buildString );
|
||||
}
|
||||
}
|
||||
|
||||
const QString descFooter = tr( "You can continue without setting up filesystems "
|
||||
"properly, but your system may fail to start." );
|
||||
|
||||
QString description = descHeader + startList;
|
||||
for ( const auto& item : issueList )
|
||||
{
|
||||
description += listItem( item );
|
||||
}
|
||||
description += endList + descFooter;
|
||||
|
||||
QMessageBox mb( QMessageBox::Warning, message, description, QMessageBox::Ok, m_manualPartitionPage );
|
||||
Calamares::fixButtonLabels( &mb );
|
||||
mb.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,6 +941,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
m_future->setFuture( future );
|
||||
|
||||
m_core->partitionLayout().init( m_config->defaultFsType(), configurationMap.value( "partitionLayout" ).toList() );
|
||||
m_core->dirFSRestrictLayout().init( configurationMap.value( "directoryFilesystemRestrictions" ).toList() );
|
||||
}
|
||||
|
||||
Calamares::JobList
|
||||
|
||||
@@ -39,6 +39,21 @@ class PLUGINDLLEXPORT PartitionViewStep : public Calamares::ViewStep
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct FSConflictEntry
|
||||
{
|
||||
QString conflictingPath;
|
||||
QString conflictingFilesystem;
|
||||
QString conflictedPath;
|
||||
QStringList allowableFilesystems;
|
||||
|
||||
FSConflictEntry();
|
||||
FSConflictEntry( const QString& conflictingPathArg,
|
||||
const QString& conflictingFilesystemArg,
|
||||
const QString& conflictedPathArg,
|
||||
QStringList allowableFilesystemsArg );
|
||||
FSConflictEntry( const FSConflictEntry& e ) = default;
|
||||
};
|
||||
|
||||
explicit PartitionViewStep( QObject* parent = nullptr );
|
||||
~PartitionViewStep() override;
|
||||
|
||||
|
||||
231
src/modules/partition/core/DirFSRestrictLayout.cpp
Normal file
231
src/modules/partition/core/DirFSRestrictLayout.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-FileCopyrightText: 2018-2019 Collabora Ltd <arnaud.ferraris@collabora.com>
|
||||
* SPDX-FileCopyrightText: 2024 Aaron Rainbolt <arraybolt3@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is Free Software: see the License-Identifier above.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include "core/DirFSRestrictLayout.h"
|
||||
|
||||
#include "core/KPMHelpers.h"
|
||||
#include "core/PartUtils.h"
|
||||
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
#include <kpmcore/fs/filesystemfactory.h>
|
||||
|
||||
#include <QSet>
|
||||
|
||||
DirFSRestrictLayout::DirFSRestrictLayout() {}
|
||||
|
||||
DirFSRestrictLayout::DirFSRestrictLayout( const DirFSRestrictLayout& layout )
|
||||
: m_dirFSRestrictLayout( layout.m_dirFSRestrictLayout )
|
||||
{
|
||||
}
|
||||
|
||||
DirFSRestrictLayout::~DirFSRestrictLayout() {}
|
||||
|
||||
DirFSRestrictLayout::DirFSRestrictEntry::DirFSRestrictEntry( const QString& path,
|
||||
QList< FileSystem::Type > allowedFSTypes,
|
||||
bool onlyWhenMountpoint )
|
||||
: dirPath( path )
|
||||
, dirAllowedFSTypes( allowedFSTypes )
|
||||
, useOnlyWhenMountpoint( onlyWhenMountpoint )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DirFSRestrictLayout::init( const QVariantList& config )
|
||||
{
|
||||
m_dirFSRestrictLayout.clear();
|
||||
bool efiNeedsSet = true;
|
||||
|
||||
for ( const auto& r : config )
|
||||
{
|
||||
QVariantMap pentry = r.toMap();
|
||||
if ( !pentry.contains( "directory" ) || !pentry.contains( "allowedFilesystemTypes" ) )
|
||||
{
|
||||
cError() << "Directory filesystem restriction layout entry #" << config.indexOf( r )
|
||||
<< "lacks mandatory attributes, switching to default layout.";
|
||||
m_dirFSRestrictLayout.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
QString directory = Calamares::getString( pentry, "directory" );
|
||||
QStringList allowedFSTypeStrings = Calamares::getStringList( pentry, "allowedFilesystemTypes" );
|
||||
QList< FileSystem::Type > allowedFSTypes;
|
||||
if ( allowedFSTypeStrings.length() == 1 && allowedFSTypeStrings[0] == "all" )
|
||||
{
|
||||
allowedFSTypes = fullFSList();
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( const auto& fsStr : allowedFSTypeStrings )
|
||||
{
|
||||
FileSystem::Type allowedFSType;
|
||||
PartUtils::canonicalFilesystemName( fsStr, &allowedFSType );
|
||||
if ( allowedFSType == FileSystem::Type::Unknown )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
allowedFSTypes.append( allowedFSType );
|
||||
}
|
||||
}
|
||||
bool onlyWhenMountpoint = Calamares::getBool( pentry, "onlyWhenMountpoint", false );
|
||||
if ( directory == "efi" )
|
||||
{
|
||||
efiNeedsSet = false;
|
||||
}
|
||||
DirFSRestrictEntry restrictEntry( directory, allowedFSTypes, onlyWhenMountpoint );
|
||||
m_dirFSRestrictLayout.append( restrictEntry );
|
||||
}
|
||||
|
||||
if ( efiNeedsSet )
|
||||
{
|
||||
QList< FileSystem::Type > efiAllowedFSTypes = { FileSystem::Fat32 };
|
||||
DirFSRestrictEntry efiRestrictEntry( "efi", efiAllowedFSTypes, true );
|
||||
m_dirFSRestrictLayout.append( efiRestrictEntry );
|
||||
}
|
||||
}
|
||||
|
||||
QList< FileSystem::Type >
|
||||
DirFSRestrictLayout::allowedFSTypes( const QString& path, const QStringList& existingMountpoints, bool overlayDirs )
|
||||
{
|
||||
QSet< FileSystem::Type > typeSet;
|
||||
bool foundTypeList = false;
|
||||
|
||||
for ( const auto& entry : m_dirFSRestrictLayout )
|
||||
{
|
||||
QString dirPath = entry.dirPath;
|
||||
if ( dirPath == "efi" )
|
||||
{
|
||||
dirPath = Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
|
||||
}
|
||||
if ( dirPath == path || ( !entry.useOnlyWhenMountpoint && overlayDirs && path.startsWith( QStringLiteral( "/" ) ) && dirPath.startsWith( path ) && !existingMountpoints.contains( dirPath ) ) )
|
||||
{
|
||||
QSet< FileSystem::Type > newTypeSet = QSet< FileSystem::Type >( entry.dirAllowedFSTypes.cbegin(), entry.dirAllowedFSTypes.cend() );
|
||||
foundTypeList = true;
|
||||
if ( typeSet.isEmpty() )
|
||||
{
|
||||
typeSet = newTypeSet;
|
||||
if ( !overlayDirs )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typeSet.intersect( newTypeSet );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( overlayDirs )
|
||||
{
|
||||
QList< FileSystem::Type > anyTypeList = anyAllowedFSTypes();
|
||||
QSet< FileSystem::Type > anyTypeSet = QSet< FileSystem::Type >( anyTypeList.cbegin(), anyTypeList.cend() );
|
||||
if ( !foundTypeList )
|
||||
{
|
||||
typeSet = anyTypeSet;
|
||||
foundTypeList = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
typeSet.intersect( anyTypeSet );
|
||||
}
|
||||
}
|
||||
|
||||
if ( foundTypeList )
|
||||
{
|
||||
return QList< FileSystem::Type >( typeSet.cbegin(), typeSet.cend() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// This directory doesn't have any allowed filesystems explicitly
|
||||
// configured, so all filesystems are valid.
|
||||
return fullFSList();
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
DirFSRestrictLayout::diagnoseFSConflict( const QString& path, const FileSystem::Type& fsType, const QStringList& existingMountpoints )
|
||||
{
|
||||
QSet< FileSystem::Type > typeSet;
|
||||
bool foundTypeList = false;
|
||||
|
||||
for ( const auto& entry : m_dirFSRestrictLayout )
|
||||
{
|
||||
QString dirPath = entry.dirPath;
|
||||
if ( dirPath == "efi" )
|
||||
{
|
||||
dirPath = Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
|
||||
}
|
||||
if ( dirPath == path || ( !entry.useOnlyWhenMountpoint && path.startsWith( QStringLiteral( "/" ) ) && ( dirPath.startsWith( path ) || dirPath == "any" ) && !existingMountpoints.contains( dirPath ) ) )
|
||||
{
|
||||
QSet< FileSystem::Type > newTypeSet = QSet< FileSystem::Type >( entry.dirAllowedFSTypes.cbegin(), entry.dirAllowedFSTypes.cend() );
|
||||
foundTypeList = true;
|
||||
if ( typeSet.isEmpty() )
|
||||
{
|
||||
typeSet = newTypeSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
typeSet.intersect( newTypeSet );
|
||||
}
|
||||
}
|
||||
|
||||
if ( foundTypeList && !typeSet.contains( fsType ) )
|
||||
{
|
||||
if ( typeSet.isEmpty() )
|
||||
{
|
||||
cWarning() << "no filesystems are valid for path '" << path << "', check directoryFilesystemRestrictions for issues";
|
||||
}
|
||||
// At this point, we've found the first mountpoint that, when
|
||||
// taken into account, results in the currently chosen filesystem
|
||||
// being invalid. Return that mountpoint.
|
||||
return dirPath;
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList< FileSystem::Type >
|
||||
DirFSRestrictLayout::anyAllowedFSTypes()
|
||||
{
|
||||
for ( const auto& entry : m_dirFSRestrictLayout )
|
||||
{
|
||||
if ( entry.dirPath == "any" )
|
||||
{
|
||||
return entry.dirAllowedFSTypes;
|
||||
}
|
||||
}
|
||||
|
||||
// No global filesystem whitelist defined, so all filesystems are
|
||||
// considered valid unless a mountpoint-specific whitelist is used to
|
||||
// restrict the allowed filesystems.
|
||||
return fullFSList();
|
||||
}
|
||||
|
||||
QList< FileSystem::Type >
|
||||
DirFSRestrictLayout::fullFSList()
|
||||
{
|
||||
QList< FileSystem::Type > typeList;
|
||||
FileSystemFactory::init();
|
||||
for ( auto fs : FileSystemFactory::map() )
|
||||
{
|
||||
typeList.append( fs->type() );
|
||||
}
|
||||
return typeList;
|
||||
}
|
||||
87
src/modules/partition/core/DirFSRestrictLayout.h
Normal file
87
src/modules/partition/core/DirFSRestrictLayout.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2018-2019 Collabora Ltd <arnaud.ferraris@collabora.com>
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-FileCopyrightText: 2024 Aaron Rainbolt <arraybolt3@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is Free Software: see the License-Identifier above.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIRFSRESTRICTLAYOUT_H
|
||||
#define DIRFSRESTRICTLAYOUT_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
// KPMcore
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
// Qt
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
class DirFSRestrictLayout
|
||||
{
|
||||
public:
|
||||
struct DirFSRestrictEntry
|
||||
{
|
||||
QString dirPath;
|
||||
QList< FileSystem::Type > dirAllowedFSTypes;
|
||||
bool useOnlyWhenMountpoint = false;
|
||||
|
||||
/// @brief All-zeroes DirFSRestrictEntry
|
||||
DirFSRestrictEntry() = default;
|
||||
/** @brief Parse @p path, @p allowedFSTypes, and @p onlyWhenMountpoint to their respective member variables
|
||||
*
|
||||
* Sets a specific set of allowed filesystems for a mountpoint.
|
||||
*/
|
||||
DirFSRestrictEntry( const QString& path,
|
||||
QList< FileSystem::Type > allowedFSTypes,
|
||||
bool onlyWhenMountpoint );
|
||||
/// @brief Copy DirFSRestrictEntry
|
||||
DirFSRestrictEntry( const DirFSRestrictEntry& e ) = default;
|
||||
};
|
||||
|
||||
DirFSRestrictLayout();
|
||||
DirFSRestrictLayout( const DirFSRestrictLayout& layout );
|
||||
~DirFSRestrictLayout();
|
||||
|
||||
/** @brief create the configuration from @p config
|
||||
*
|
||||
* @p config is a list of partition entries (in QVariant form,
|
||||
* read from YAML). If no entries are given, the only restriction is that
|
||||
* the EFI system partition must use fat32.
|
||||
*
|
||||
* Any unknown values in the config will be ignored.
|
||||
*/
|
||||
void init( const QVariantList& config );
|
||||
|
||||
/** @brief get a list of allowable filesystems for a path
|
||||
*
|
||||
* @p path is the path one wants to get the allowed FS types for.
|
||||
* @p existingMountpoints is the list of all mountpoints that are
|
||||
* currently configured to be placed on their own partition.
|
||||
*/
|
||||
QList< FileSystem::Type > allowedFSTypes( const QString& path, const QStringList& existingMountpoints, bool overlayDirs );
|
||||
|
||||
/** @brief determine which directory restriction rule makes a particular mountpoint + filesystem combination invalid
|
||||
*
|
||||
* @p path is the path with an improper filesystem chosen.
|
||||
* @p fsType is the improper filesystem used on that path.
|
||||
* @p existingMountpoints is the list of all mountpoints that are
|
||||
* currently configured to be placed on their own partition.
|
||||
*/
|
||||
QString diagnoseFSConflict( const QString& path, const FileSystem::Type& fsType, const QStringList& existingMountpoints );
|
||||
|
||||
/// @brief get a global filesystem whitelist
|
||||
QList< FileSystem::Type > anyAllowedFSTypes();
|
||||
|
||||
private:
|
||||
QList< DirFSRestrictEntry > m_dirFSRestrictLayout;
|
||||
|
||||
QList< FileSystem::Type > fullFSList();
|
||||
};
|
||||
|
||||
#endif /* DIRFSRESTRICTLAYOUT_H */
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "core/KPMHelpers.h"
|
||||
#include "core/PartitionLayout.h"
|
||||
#include "core/PartitionModel.h"
|
||||
#include "core/DirFSRestrictLayout.h"
|
||||
#include "jobs/PartitionJob.h"
|
||||
|
||||
#include "Job.h"
|
||||
@@ -167,6 +168,9 @@ public:
|
||||
*/
|
||||
PartitionLayout& partitionLayout() { return m_partLayout; }
|
||||
|
||||
/// @brief Get the directory filesystem restriction layout.
|
||||
DirFSRestrictLayout& dirFSRestrictLayout() { return m_dirFSRestrictLayout; }
|
||||
|
||||
void layoutApply( Device* dev,
|
||||
qint64 firstSector,
|
||||
qint64 lastSector,
|
||||
@@ -270,6 +274,7 @@ private:
|
||||
bool m_isDirty = false;
|
||||
QString m_bootLoaderInstallPath;
|
||||
PartitionLayout m_partLayout;
|
||||
DirFSRestrictLayout m_dirFSRestrictLayout;
|
||||
|
||||
OsproberEntryList m_osproberLines;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "core/KPMHelpers.h"
|
||||
#include "core/PartUtils.h"
|
||||
#include "core/PartitionInfo.h"
|
||||
#include "core/PartitionCoreModule.h"
|
||||
#include "gui/PartitionDialogHelpers.h"
|
||||
#include "gui/PartitionSizeController.h"
|
||||
|
||||
@@ -46,18 +47,14 @@
|
||||
using Calamares::Partition::untranslatedFS;
|
||||
using Calamares::Partition::userVisibleFS;
|
||||
|
||||
static QSet< FileSystem::Type > s_unmountableFS( { FileSystem::Unformatted,
|
||||
FileSystem::LinuxSwap,
|
||||
FileSystem::Extended,
|
||||
FileSystem::Unknown,
|
||||
FileSystem::Lvm2_PV } );
|
||||
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog::CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
PartitionNode* parentPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: QDialog( parentWidget )
|
||||
, m_ui( new Ui_CreatePartitionDialog )
|
||||
, m_core( core )
|
||||
, m_partitionSizeController( new PartitionSizeController( this ) )
|
||||
, m_device( device )
|
||||
, m_parent( parentPartition )
|
||||
@@ -128,17 +125,23 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
this,
|
||||
&CreatePartitionDialog::checkMountPointSelection );
|
||||
|
||||
connect( m_ui->fsComboBox,
|
||||
&QComboBox::currentTextChanged,
|
||||
this,
|
||||
&CreatePartitionDialog::checkMountPointSelection );
|
||||
|
||||
// Select a default
|
||||
m_ui->fsComboBox->setCurrentIndex( defaultFsIndex );
|
||||
updateMountPointUi();
|
||||
checkMountPointSelection();
|
||||
}
|
||||
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog::CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
const FreeSpace& freeSpacePartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: CreatePartitionDialog( device, freeSpacePartition.p->parent(), usedMountPoints, parentWidget )
|
||||
: CreatePartitionDialog( core, device, freeSpacePartition.p->parent(), usedMountPoints, parentWidget )
|
||||
{
|
||||
standardMountPoints( *( m_ui->mountPointComboBox ), QString() );
|
||||
setFlagList( *( m_ui->m_listFlags ),
|
||||
@@ -147,11 +150,12 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
initPartResizerWidget( freeSpacePartition.p );
|
||||
}
|
||||
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog::CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
const FreshPartition& existingNewPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: CreatePartitionDialog( device, existingNewPartition.p->parent(), usedMountPoints, parentWidget )
|
||||
: CreatePartitionDialog( core, device, existingNewPartition.p->parent(), usedMountPoints, parentWidget )
|
||||
{
|
||||
standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( existingNewPartition.p ) );
|
||||
setFlagList( *( m_ui->m_listFlags ),
|
||||
@@ -343,8 +347,10 @@ CreatePartitionDialog::updateMountPointUi()
|
||||
void
|
||||
CreatePartitionDialog::checkMountPointSelection()
|
||||
{
|
||||
validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ),
|
||||
validateMountPoint( m_core,
|
||||
selectedMountPoint( m_ui->mountPointComboBox ),
|
||||
m_usedMountPoints,
|
||||
m_ui->fsComboBox->currentText(),
|
||||
m_ui->mountPointExplanation,
|
||||
m_ui->buttonBox->button( QDialogButtonBox::Ok ) );
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <QDialog>
|
||||
#include <QScopedPointer>
|
||||
|
||||
|
||||
class PartitionCoreModule;
|
||||
class Device;
|
||||
class Partition;
|
||||
class PartitionNode;
|
||||
@@ -39,7 +39,8 @@ private:
|
||||
*
|
||||
* This does all the shared UI setup.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
PartitionNode* parentPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget );
|
||||
@@ -59,7 +60,8 @@ public:
|
||||
* Creating from free space makes a wholly new partition with
|
||||
* no flags set at all.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
const FreeSpace& freeSpacePartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget = nullptr );
|
||||
@@ -68,7 +70,8 @@ public:
|
||||
* A partition previously newly created (e.g. via this dialog
|
||||
* and the constructor above) can be re-edited.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
CreatePartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
const FreshPartition& existingNewPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget = nullptr );
|
||||
@@ -84,6 +87,7 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
QScopedPointer< Ui_CreatePartitionDialog > m_ui;
|
||||
PartitionCoreModule* m_core;
|
||||
PartitionSizeController* m_partitionSizeController;
|
||||
Device* m_device;
|
||||
PartitionNode* m_parent;
|
||||
|
||||
@@ -57,12 +57,14 @@ updateLabel( PartitionCoreModule* core, Device* device, Partition* partition, co
|
||||
}
|
||||
}
|
||||
|
||||
EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
|
||||
EditExistingPartitionDialog::EditExistingPartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
Partition* partition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: QDialog( parentWidget )
|
||||
, m_ui( new Ui_EditExistingPartitionDialog )
|
||||
, m_core( core )
|
||||
, m_device( device )
|
||||
, m_partition( partition )
|
||||
, m_partitionSizeController( new PartitionSizeController( this ) )
|
||||
@@ -81,6 +83,11 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
|
||||
this,
|
||||
&EditExistingPartitionDialog::checkMountPointSelection );
|
||||
|
||||
connect( m_ui->fileSystemComboBox,
|
||||
&QComboBox::currentTextChanged,
|
||||
this,
|
||||
&EditExistingPartitionDialog::checkMountPointSelection );
|
||||
|
||||
// The filesystem label field is always enabled, because we may want to change
|
||||
// the label on the current filesystem without formatting.
|
||||
m_ui->fileSystemLabelEdit->setText( PartitionInfo::label( m_partition ) );
|
||||
@@ -345,8 +352,10 @@ EditExistingPartitionDialog::updateMountPointPicker()
|
||||
void
|
||||
EditExistingPartitionDialog::checkMountPointSelection()
|
||||
{
|
||||
if ( validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ),
|
||||
if ( validateMountPoint( m_core,
|
||||
selectedMountPoint( m_ui->mountPointComboBox ),
|
||||
m_usedMountPoints,
|
||||
m_ui->fileSystemComboBox->currentText(),
|
||||
m_ui->mountPointExplanation,
|
||||
m_ui->buttonBox->button( QDialogButtonBox::Ok ) ) )
|
||||
{
|
||||
|
||||
@@ -37,7 +37,8 @@ public:
|
||||
Partition* p;
|
||||
};
|
||||
|
||||
EditExistingPartitionDialog( Device* device,
|
||||
EditExistingPartitionDialog( PartitionCoreModule* core,
|
||||
Device* device,
|
||||
Partition* partition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget = nullptr );
|
||||
@@ -50,6 +51,7 @@ private slots:
|
||||
|
||||
private:
|
||||
QScopedPointer< Ui_EditExistingPartitionDialog > m_ui;
|
||||
PartitionCoreModule* m_core;
|
||||
Device* m_device;
|
||||
Partition* m_partition;
|
||||
PartitionSizeController* m_partitionSizeController;
|
||||
|
||||
@@ -12,12 +12,15 @@
|
||||
#include "PartitionDialogHelpers.h"
|
||||
|
||||
#include "core/PartUtils.h"
|
||||
#include "core/PartitionCoreModule.h"
|
||||
#include "gui/CreatePartitionDialog.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
@@ -81,7 +84,7 @@ setSelectedMountPoint( QComboBox& combo, const QString& selected )
|
||||
}
|
||||
|
||||
bool
|
||||
validateMountPoint( const QString& mountPoint, const QStringList& inUse, QLabel* label, QPushButton* button )
|
||||
validateMountPoint( PartitionCoreModule* core, const QString& mountPoint, const QStringList& inUse, const QString& fileSystem, QLabel* label, QPushButton* button )
|
||||
{
|
||||
QString msg;
|
||||
bool ok = true;
|
||||
@@ -95,6 +98,58 @@ validateMountPoint( const QString& mountPoint, const QStringList& inUse, QLabel*
|
||||
{
|
||||
msg = CreatePartitionDialog::tr( "Mountpoint must start with a <tt>/</tt>.", "@info" );
|
||||
ok = false;
|
||||
} else {
|
||||
// Validate the chosen filesystem + mountpoint combination.
|
||||
FileSystem::Type selectedFsType;
|
||||
PartUtils::canonicalFilesystemName( fileSystem, &selectedFsType );
|
||||
bool fsTypeIsAllowed = false;
|
||||
if ( selectedFsType == FileSystem::Type::Unknown )
|
||||
{
|
||||
fsTypeIsAllowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QList< FileSystem::Type > anyAllowedFsTypes = core->dirFSRestrictLayout().anyAllowedFSTypes();
|
||||
for ( auto& anyAllowedFsType : anyAllowedFsTypes )
|
||||
{
|
||||
if ( selectedFsType == anyAllowedFsType )
|
||||
{
|
||||
fsTypeIsAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool fsTypeIsAllowedForMountPoint = false;
|
||||
// We allow arbitrary unmountable filesystems here since an
|
||||
// unmountable filesystem has no mount point associated with it, thus
|
||||
// any filesystem restriction we'd find at this point would be
|
||||
// irrelevant.
|
||||
if ( selectedFsType == FileSystem::Type::Unknown || s_unmountableFS.contains( selectedFsType ) )
|
||||
{
|
||||
fsTypeIsAllowedForMountPoint = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QList< FileSystem::Type > allowedFsTypes = core->dirFSRestrictLayout().allowedFSTypes( mountPoint, inUse, false );
|
||||
for ( auto& allowedFsType : allowedFsTypes )
|
||||
{
|
||||
if ( selectedFsType == allowedFsType )
|
||||
{
|
||||
fsTypeIsAllowedForMountPoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !fsTypeIsAllowed ) {
|
||||
msg = CreatePartitionDialog::tr( "Filesystem is prohibited by this distro. Consider selecting another one.", "@info" );
|
||||
ok = true;
|
||||
}
|
||||
else if ( !fsTypeIsAllowedForMountPoint ) {
|
||||
msg = CreatePartitionDialog::tr( "Filesystem is prohibited for use on this mountpoint. Consider selecting a different filesystem or mountpoint.", "@info" );
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( label )
|
||||
|
||||
@@ -13,14 +13,23 @@
|
||||
#define PARTITION_GUI_PARTITIONDIALOGHELPERS
|
||||
|
||||
#include <kpmcore/core/partitiontable.h>
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
|
||||
class PartitionCoreModule;
|
||||
class QPushButton;
|
||||
class QComboBox;
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
|
||||
static QSet< FileSystem::Type > s_unmountableFS( { FileSystem::Unformatted,
|
||||
FileSystem::LinuxSwap,
|
||||
FileSystem::Extended,
|
||||
FileSystem::Unknown,
|
||||
FileSystem::Lvm2_PV } );
|
||||
|
||||
/**
|
||||
* Returns a list of standard mount points (e.g. /, /usr, ...).
|
||||
* This also includes the EFI mount point if that is necessary
|
||||
@@ -68,7 +77,7 @@ setSelectedMountPoint( QComboBox* combo, const QString& selected )
|
||||
* If it is not valid, returns @c false and sets the UI
|
||||
* to explain why.
|
||||
*/
|
||||
bool validateMountPoint( const QString& mountPoint, const QStringList& inUse, QLabel* label, QPushButton* button );
|
||||
bool validateMountPoint( PartitionCoreModule* core, const QString& mountPoint, const QStringList& inUse, const QString& fileSystem, QLabel* label, QPushButton* button );
|
||||
|
||||
/**
|
||||
* Get the flags that have been checked in the list widget.
|
||||
|
||||
@@ -411,7 +411,7 @@ PartitionPage::onCreateClicked()
|
||||
}
|
||||
|
||||
QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog(
|
||||
model->device(), CreatePartitionDialog::FreeSpace { partition }, getCurrentUsedMountpoints(), this );
|
||||
m_core, model->device(), CreatePartitionDialog::FreeSpace { partition }, getCurrentUsedMountpoints(), this );
|
||||
if ( dlg->exec() == QDialog::Accepted )
|
||||
{
|
||||
Partition* newPart = dlg->getNewlyCreatedPartition();
|
||||
@@ -515,7 +515,7 @@ PartitionPage::updatePartitionToCreate( Device* device, Partition* partition )
|
||||
mountPoints.removeOne( PartitionInfo::mountPoint( partition ) );
|
||||
|
||||
QPointer< CreatePartitionDialog > dlg
|
||||
= new CreatePartitionDialog( device, CreatePartitionDialog::FreshPartition { partition }, mountPoints, this );
|
||||
= new CreatePartitionDialog( m_core, device, CreatePartitionDialog::FreshPartition { partition }, mountPoints, this );
|
||||
if ( dlg->exec() == QDialog::Accepted )
|
||||
{
|
||||
Partition* newPartition = dlg->getNewlyCreatedPartition();
|
||||
@@ -532,7 +532,7 @@ PartitionPage::editExistingPartition( Device* device, Partition* partition )
|
||||
mountPoints.removeOne( PartitionInfo::mountPoint( partition ) );
|
||||
|
||||
QPointer< EditExistingPartitionDialog > dlg
|
||||
= new EditExistingPartitionDialog( device, partition, mountPoints, this );
|
||||
= new EditExistingPartitionDialog( m_core, device, partition, mountPoints, this );
|
||||
if ( dlg->exec() == QDialog::Accepted )
|
||||
{
|
||||
dlg->applyChanges( m_core );
|
||||
|
||||
@@ -223,6 +223,49 @@ defaultFileSystemType: "ext4"
|
||||
# warning (this matches traditional no-choice-available behavior best).
|
||||
# availableFileSystemTypes: ["ext4","f2fs"]
|
||||
|
||||
# Per-directory filesystem restrictions.
|
||||
#
|
||||
# This optional setting specifies what filesystems the user can and cannot use
|
||||
# for various directories and mountpoints when using manual partitioning.
|
||||
#
|
||||
# If nothing is specified, the only restriction enforced by default is that
|
||||
# the EFI system partition must use the fat32 filesystem.
|
||||
#
|
||||
# Otherwise, the filesystem restrictions are defined as follow:
|
||||
#
|
||||
# directoryFilesystemRestrictions:
|
||||
# - directory: "any"
|
||||
# allowedFilesystemTypes: ["all"]
|
||||
# - directory: "/"
|
||||
# allowedFilesystemTypes: ["ext4","xfs","btrfs","jfs","f2fs"]
|
||||
# - mountpoint: "efi"
|
||||
# allowedFilesystemTypes: ["fat32"]
|
||||
# onlyWhenMountpoint: true
|
||||
#
|
||||
# There can be any number of mountpoints listed, each entry having the
|
||||
# following attributes:
|
||||
# - mountpoint: mountpoint's full path
|
||||
# or
|
||||
# "any" to specify a global whitelist that applies to all
|
||||
# mountpoints
|
||||
# or
|
||||
# "efi" to specify a whitelist specific to the EFI system
|
||||
# partition, wherever that partition is located
|
||||
# - allowedFilesystemTypes: the list of all filesystems valid for this
|
||||
# mountpoint. If the list contains exactly one
|
||||
# element, and that element is the special value
|
||||
# "any", all filesystem types recognized by
|
||||
# Calamares will be allowed.
|
||||
# - onlyWhenMountpoint: Whether the restriction should apply only when the
|
||||
# specified directory is a mountpoint. When set to
|
||||
# true, Calamares will only enforce the listed
|
||||
# restrictions when the user makes a separate partition
|
||||
# for this directory and assigns the mountpoint
|
||||
# accordingly. When set to false, Calamares will
|
||||
# ensure this directory uses the specified filesystem
|
||||
# even if the directory is part of a filesystem on a
|
||||
# different mountpoint. Defaults to false.
|
||||
|
||||
# Show/hide LUKS related functionality in automated partitioning modes.
|
||||
# Disable this if you choose not to deploy early unlocking support in GRUB2
|
||||
# and/or your distribution's initramfs solution.
|
||||
|
||||
@@ -37,6 +37,7 @@ properties:
|
||||
|
||||
defaultFileSystemType: { type: string }
|
||||
availableFileSystemTypes: { type: array, items: { type: string } }
|
||||
mountpointFilesystemRestrictions: { type: array } # TODO: specify items
|
||||
|
||||
luksGeneration: { type: string, enum: [luks1, luks2] } # Also allows "luks" as alias of "luks1"
|
||||
enableLuksAutomatedPartitioning: { type: boolean, default: false }
|
||||
|
||||
Reference in New Issue
Block a user