From d3135898fd195915fb7ec832d895defc8387b5d4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 17:35:07 +0200 Subject: [PATCH 01/72] [users] More fine-grained group descriptions Describe groups with more detail: - groups can be system groups (low GID) or not - groups may be pre-configured (e.g. come from the unpackfs stage) --- src/modules/users/Config.cpp | 16 ++++++++++--- src/modules/users/Config.h | 44 ++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index d0f573286..e190b30dc 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -590,8 +590,12 @@ Config::checkReady() STATICTEST void -setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups ) +setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription >& defaultGroups ) { + defaultGroups.clear(); + auto groupsFromConfig = map.value( "defaultGroups" ).toList(); + cDebug() << groupsFromConfig; +#if 0 // '#' is not a valid group name; use that to distinguish an empty-list // in the configuration (which is a legitimate, if unusual, choice) // from a bad or missing configuration value. @@ -601,6 +605,7 @@ setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroup cWarning() << "Using fallback groups. Please check *defaultGroups* in users.conf"; defaultGroups = QStringList { "lp", "video", "network", "storage", "wheel", "audio" }; } +#endif } STATICTEST HostNameActions @@ -737,8 +742,13 @@ Config::createJobs() const Calamares::Job* j; - j = new CreateUserJob( - loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), defaultGroups() ); + QStringList groupNames = std::accumulate( + m_defaultGroups.begin(), + m_defaultGroups.end(), + QStringList(), + []( const QStringList& l, const GroupDescription& g ) { return QStringList( l ) << g.name(); } ); + + j = new CreateUserJob( loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), groupNames ); jobs.append( Calamares::job_ptr( j ) ); j = new SetPasswordJob( loginName(), userPassword() ); diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index e4057941c..384575ed4 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -15,6 +15,7 @@ #include "Job.h" #include "utils/NamedEnum.h" +#include #include #include @@ -30,6 +31,45 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( HostNameActions ) const NamedEnumTable< HostNameAction >& hostNameActionNames(); +/** @brief Settings for a single group + * + * The list of defaultgroups from the configuration can be + * set up in a fine-grained way, with both user- and system- + * level groups; this class stores a configuration for each. + */ +class GroupDescription +{ +public: + ///@brief An invalid, empty group + GroupDescription() {} + + ///@brief A group with full details + GroupDescription( const QString& name, bool mustExistAlready = false, bool isSystem = false ) + : m_name( name ) + , m_isValid( !name.isEmpty() ) + , m_mustAlreadyExist( mustExistAlready ) + , m_isSystem( isSystem ) + { + } + + bool isValid() const { return m_isValid; } + bool isSystemGroup() const { return m_isSystem; } + QString name() const { return m_name; } + + ///@brief Equality of groups depends only on name and kind + bool operator==( const GroupDescription& rhs ) const + { + return rhs.name() == name() && rhs.isSystemGroup() == isSystemGroup(); + } + +private: + QString m_name; + bool m_isValid = false; + bool m_mustAlreadyExist = false; + bool m_isSystem = false; +}; + + class Config : public QObject { Q_OBJECT @@ -158,7 +198,7 @@ public: /// Current setting for "require strong password"? bool requireStrongPasswords() const { return m_requireStrongPasswords; } - const QStringList& defaultGroups() const { return m_defaultGroups; } + const QList< GroupDescription >& defaultGroups() const { return m_defaultGroups; } // The user enters a password (and again in a separate UI element) QString userPassword() const { return m_userPassword; } @@ -242,7 +282,7 @@ private: PasswordStatus passwordStatus( const QString&, const QString& ) const; void checkReady(); - QStringList m_defaultGroups; + QList< GroupDescription > m_defaultGroups; QString m_userShell; QString m_autologinGroup; QString m_sudoersGroup; From e46d9f735d8c6fd2ebc0e72124d7360d1e0d1b82 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 17:36:24 +0200 Subject: [PATCH 02/72] [users] Adjust tests to changed groups-list --- src/modules/users/Tests.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 9ed7718c7..ac3a03446 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -16,7 +16,7 @@ #include // Implementation details -extern void setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups ); +extern void setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription >& defaultGroups ); extern HostNameActions getHostNameActions( const QVariantMap& configurationMap ); extern bool addPasswordCheck( const QString& key, const QVariant& value, PasswordCheckList& passwordChecks ); @@ -56,29 +56,32 @@ void UserTests::testDefaultGroups() { { - QStringList groups; + QList< GroupDescription > groups; QVariantMap hweelGroup; QVERIFY( groups.isEmpty() ); hweelGroup.insert( "defaultGroups", QStringList { "hweel" } ); setConfigurationDefaultGroups( hweelGroup, groups ); QCOMPARE( groups.count(), 1 ); - QVERIFY( groups.contains( "hweel" ) ); + QVERIFY( groups.contains( GroupDescription( "hweel" ) ) ); } { QStringList desired { "wheel", "root", "operator" }; - QStringList groups; + QList< GroupDescription > groups; QVariantMap threeGroup; QVERIFY( groups.isEmpty() ); threeGroup.insert( "defaultGroups", desired ); setConfigurationDefaultGroups( threeGroup, groups ); QCOMPARE( groups.count(), 3 ); - QVERIFY( !groups.contains( "hweel" ) ); - QCOMPARE( groups, desired ); + QVERIFY( !groups.contains( GroupDescription( "hweel" ) ) ); + for ( const auto& s : desired ) + { + QVERIFY( groups.contains( GroupDescription( s ) ) ); + } } { - QStringList groups; + QList< GroupDescription > groups; QVariantMap explicitEmpty; QVERIFY( groups.isEmpty() ); explicitEmpty.insert( "defaultGroups", QStringList() ); @@ -87,22 +90,22 @@ UserTests::testDefaultGroups() } { - QStringList groups; + QList< GroupDescription > groups; QVariantMap missing; QVERIFY( groups.isEmpty() ); setConfigurationDefaultGroups( missing, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( "lp" ) ); + QVERIFY( groups.contains( GroupDescription( "lp" ) ) ); } { - QStringList groups; + QList< GroupDescription > groups; QVariantMap typeMismatch; QVERIFY( groups.isEmpty() ); typeMismatch.insert( "defaultGroups", 1 ); setConfigurationDefaultGroups( typeMismatch, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( "lp" ) ); + QVERIFY( groups.contains( GroupDescription( "lp" ) ) ); } } From ceeab7087cd0ad792390615eda0e1dc8fa9fb17d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 22:12:26 +0200 Subject: [PATCH 03/72] [users] Fix implementation so existing tests pass --- src/modules/users/Config.cpp | 42 ++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index e190b30dc..73465edc2 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -593,19 +593,39 @@ STATICTEST void setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription >& defaultGroups ) { defaultGroups.clear(); - auto groupsFromConfig = map.value( "defaultGroups" ).toList(); - cDebug() << groupsFromConfig; -#if 0 - // '#' is not a valid group name; use that to distinguish an empty-list - // in the configuration (which is a legitimate, if unusual, choice) - // from a bad or missing configuration value. - defaultGroups = CalamaresUtils::getStringList( map, QStringLiteral( "defaultGroups" ), QStringList { "#" } ); - if ( defaultGroups.contains( QStringLiteral( "#" ) ) ) + + const QString key( "defaultGroups" ); + auto groupsFromConfig = map.value( key ).toList(); + if ( groupsFromConfig.isEmpty() ) { - cWarning() << "Using fallback groups. Please check *defaultGroups* in users.conf"; - defaultGroups = QStringList { "lp", "video", "network", "storage", "wheel", "audio" }; + if ( map.contains( key ) && map.value( key ).isValid() && map.value( key ).canConvert( QVariant::List ) ) + { + // Explicitly set, but empty: this is valid, but unusual. + cDebug() << key << "has explicit empty value."; + } + else + { + cWarning() << "Using fallback groups. Please check *defaultGroups* value in users.conf"; + for ( const auto& s : { "lp", "video", "network", "storage", "wheel", "audio" } ) + { + defaultGroups.append( GroupDescription( s ) ); + } + } + } + else + { + for ( const auto& v : groupsFromConfig ) + { + if ( v.type() == QVariant::String ) + { + defaultGroups.append( GroupDescription( v.toString() ) ); + } + else + { + cWarning() << "Unknown *defaultGroups* entry" << v; + } + } } -#endif } STATICTEST HostNameActions From b20c80a28c6221f921046aebfe7cba034fe5f490 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 22:58:02 +0200 Subject: [PATCH 04/72] [users] Introduce class-scoped aliases for true and false for the bools This is somewhat experimental and weird; the idea is that bool arguments are a lot easier to understand if there are proper names attached, rather than "true" and "false". --- src/modules/users/Config.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index 384575ed4..853d65b5f 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -40,11 +40,17 @@ const NamedEnumTable< HostNameAction >& hostNameActionNames(); class GroupDescription { public: + // TODO: still too-weakly typed, add a macro to define strongly-typed bools + class MustExist : public std::true_type {}; + class CreateIfNeeded : public std::false_type {}; + class SystemGroup : public std::true_type {}; + class UserGroup : public std::false_type {}; + ///@brief An invalid, empty group GroupDescription() {} ///@brief A group with full details - GroupDescription( const QString& name, bool mustExistAlready = false, bool isSystem = false ) + GroupDescription( const QString& name, bool mustExistAlready = CreateIfNeeded{}, bool isSystem = UserGroup{} ) : m_name( name ) , m_isValid( !name.isEmpty() ) , m_mustAlreadyExist( mustExistAlready ) From ff9abdfc08f71386a4b48d3a89e3e01d77616fc2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 22:58:30 +0200 Subject: [PATCH 05/72] [users] The fallback groups are all **system** groups --- src/modules/users/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index 73465edc2..45b273a46 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -608,7 +608,7 @@ setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription > cWarning() << "Using fallback groups. Please check *defaultGroups* value in users.conf"; for ( const auto& s : { "lp", "video", "network", "storage", "wheel", "audio" } ) { - defaultGroups.append( GroupDescription( s ) ); + defaultGroups.append( GroupDescription( s, GroupDescription::CreateIfNeeded{}, GroupDescription::SystemGroup{} ) ); } } } From 07027c24304ac7cb9ce8cb7563f4e050a9682baa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 23:00:12 +0200 Subject: [PATCH 06/72] [users] Test distinguishes system groups from user groups --- src/modules/users/Tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index ac3a03446..6df215e02 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -95,7 +95,7 @@ UserTests::testDefaultGroups() QVERIFY( groups.isEmpty() ); setConfigurationDefaultGroups( missing, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp" ) ) ); + QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup{} ) ) ); } { @@ -105,7 +105,7 @@ UserTests::testDefaultGroups() typeMismatch.insert( "defaultGroups", 1 ); setConfigurationDefaultGroups( typeMismatch, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp" ) ) ); + QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup{} ) ) ); } } From a86374386b18b617a7848dfcfe803678e7ea4e83 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 23:13:23 +0200 Subject: [PATCH 07/72] [users] Add test for new notation for groups-with-details --- src/modules/users/Tests.cpp | 1 + src/modules/users/tests/5-issue-1523.conf | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/modules/users/tests/5-issue-1523.conf diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 6df215e02..1716034fc 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -119,6 +119,7 @@ UserTests::testDefaultGroupsYAML_data() QTest::newRow( "users.conf" ) << "users.conf" << 7 << "video"; QTest::newRow( "dashed list" ) << "tests/4-audio.conf" << 4 << "audio"; QTest::newRow( "blocked list" ) << "tests/3-wing.conf" << 3 << "wing"; + QTest::newRow( "issue 1523" ) << "tests/5-issue-1523.conf" << 4 << "foobar"; } void diff --git a/src/modules/users/tests/5-issue-1523.conf b/src/modules/users/tests/5-issue-1523.conf new file mode 100644 index 000000000..a0c5e49ba --- /dev/null +++ b/src/modules/users/tests/5-issue-1523.conf @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +--- +defaultGroups: + - adm + - name: foo + must_exist: false + system: true + - name: bar + must_exist: true + - name: foobar + must_exist: false + system: false From 02e9872a9994a3a79c18b05e98fd4f0f4eb6a34f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Oct 2020 23:30:28 +0200 Subject: [PATCH 08/72] [users] Handle detailed groups list Groups can be specified with must_exist and/or system set, so they fill in the groups list more carefully. --- src/modules/users/Config.cpp | 20 +++++++++++++++++++- src/modules/users/Config.h | 18 +++++++++++++----- src/modules/users/Tests.cpp | 4 ++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index 45b273a46..d764df846 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -605,10 +605,13 @@ setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription > } else { + // By default give the user a handful of "traditional" groups, if + // none are specified at all. These are system (GID < 1000) groups. cWarning() << "Using fallback groups. Please check *defaultGroups* value in users.conf"; for ( const auto& s : { "lp", "video", "network", "storage", "wheel", "audio" } ) { - defaultGroups.append( GroupDescription( s, GroupDescription::CreateIfNeeded{}, GroupDescription::SystemGroup{} ) ); + defaultGroups.append( + GroupDescription( s, GroupDescription::CreateIfNeeded {}, GroupDescription::SystemGroup {} ) ); } } } @@ -620,6 +623,21 @@ setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription > { defaultGroups.append( GroupDescription( v.toString() ) ); } + else if ( v.type() == QVariant::Map ) + { + const auto innermap = v.toMap(); + QString name = CalamaresUtils::getString( innermap, "name" ); + if ( !name.isEmpty() ) + { + defaultGroups.append( GroupDescription( name, + CalamaresUtils::getBool( innermap, "must_exist", false ), + CalamaresUtils::getBool( innermap, "system", false ) ) ); + } + else + { + cWarning() << "Ignoring *defaultGroups* entry without a name" << v; + } + } else { cWarning() << "Unknown *defaultGroups* entry" << v; diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index 853d65b5f..04f37d231 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -41,16 +41,24 @@ class GroupDescription { public: // TODO: still too-weakly typed, add a macro to define strongly-typed bools - class MustExist : public std::true_type {}; - class CreateIfNeeded : public std::false_type {}; - class SystemGroup : public std::true_type {}; - class UserGroup : public std::false_type {}; + class MustExist : public std::true_type + { + }; + class CreateIfNeeded : public std::false_type + { + }; + class SystemGroup : public std::true_type + { + }; + class UserGroup : public std::false_type + { + }; ///@brief An invalid, empty group GroupDescription() {} ///@brief A group with full details - GroupDescription( const QString& name, bool mustExistAlready = CreateIfNeeded{}, bool isSystem = UserGroup{} ) + GroupDescription( const QString& name, bool mustExistAlready = CreateIfNeeded {}, bool isSystem = UserGroup {} ) : m_name( name ) , m_isValid( !name.isEmpty() ) , m_mustAlreadyExist( mustExistAlready ) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 1716034fc..0ffeeae51 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -95,7 +95,7 @@ UserTests::testDefaultGroups() QVERIFY( groups.isEmpty() ); setConfigurationDefaultGroups( missing, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup{} ) ) ); + QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup {} ) ) ); } { @@ -105,7 +105,7 @@ UserTests::testDefaultGroups() typeMismatch.insert( "defaultGroups", 1 ); setConfigurationDefaultGroups( typeMismatch, groups ); QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup{} ) ) ); + QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup {} ) ) ); } } From ef70b2c32e2692ecb7907067ca9d93c29e0e8a14 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 00:23:00 +0200 Subject: [PATCH 09/72] [users] Run CreateUserJob off of the Config object - don't pass in copies or bits of the Config, hand over the whole Config - don't pluck some parts of the Config from Global Storage --- src/modules/users/Config.cpp | 8 +---- src/modules/users/CreateUserJob.cpp | 56 ++++++++++++++++------------- src/modules/users/CreateUserJob.h | 9 ++--- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index d764df846..b3d94666a 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -780,13 +780,7 @@ Config::createJobs() const Calamares::Job* j; - QStringList groupNames = std::accumulate( - m_defaultGroups.begin(), - m_defaultGroups.end(), - QStringList(), - []( const QStringList& l, const GroupDescription& g ) { return QStringList( l ) << g.name(); } ); - - j = new CreateUserJob( loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), groupNames ); + j = new CreateUserJob( this ); jobs.append( Calamares::job_ptr( j ) ); j = new SetPasswordJob( loginName(), userPassword() ); diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index 24b0f36d1..2bdb6296a 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -7,6 +7,8 @@ #include "CreateUserJob.h" +#include "Config.h" + #include "GlobalStorage.h" #include "JobQueue.h" #include "utils/CalamaresUtilsSystem.h" @@ -21,15 +23,9 @@ #include -CreateUserJob::CreateUserJob( const QString& userName, - const QString& fullName, - bool autologin, - const QStringList& defaultGroups ) +CreateUserJob::CreateUserJob( const Config* config ) : Calamares::Job() - , m_userName( userName ) - , m_fullName( fullName ) - , m_autologin( autologin ) - , m_defaultGroups( defaultGroups ) + , m_config( config ) { } @@ -37,21 +33,21 @@ CreateUserJob::CreateUserJob( const QString& userName, QString CreateUserJob::prettyName() const { - return tr( "Create user %1" ).arg( m_userName ); + return tr( "Create user %1" ).arg( m_config->loginName() ); } QString CreateUserJob::prettyDescription() const { - return tr( "Create user %1." ).arg( m_userName ); + return tr( "Create user %1." ).arg( m_config->loginName() ); } QString CreateUserJob::prettyStatusMessage() const { - return tr( "Creating user %1." ).arg( m_userName ); + return tr( "Creating user %1." ).arg( m_config->loginName() ); } STATICTEST QStringList @@ -86,16 +82,16 @@ groupsInTargetSystem( const QDir& targetRoot ) } static void -ensureGroupsExistInTarget( const QStringList& wantedGroups, const QStringList& availableGroups ) +ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, const QStringList& availableGroups ) { - for ( const QString& group : wantedGroups ) + for ( const auto& group : wantedGroups ) { - if ( !availableGroups.contains( group ) ) + if ( group.isValid() && !availableGroups.contains( group.name() ) ) { #ifdef __FreeBSD__ - CalamaresUtils::System::instance()->targetEnvCall( { "pw", "groupadd", "-n", group } ); + CalamaresUtils::System::instance()->targetEnvCall( { "pw", "groupadd", "-n", group.name() } ); #else - CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group } ); + CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group.name() } ); #endif } } @@ -189,19 +185,29 @@ CreateUserJob::exec() cDebug() << "[CREATEUSER]: preparing groups"; + // loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), groupNames ); + const auto& defaultGroups = m_config->defaultGroups(); + QStringList groupsForThisUser = std::accumulate( + defaultGroups.begin(), + defaultGroups.end(), + QStringList(), + []( const QStringList& l, const GroupDescription& g ) { return QStringList( l ) << g.name(); } ); + QStringList availableGroups = groupsInTargetSystem( destDir ); - QStringList groupsForThisUser = m_defaultGroups; - if ( m_autologin && gs->contains( "autologinGroup" ) && !gs->value( "autologinGroup" ).toString().isEmpty() ) + ensureGroupsExistInTarget( defaultGroups, availableGroups ); + + if ( m_config->doAutoLogin() && !m_config->autologinGroup().isEmpty() ) { - groupsForThisUser << gs->value( "autologinGroup" ).toString(); + const QString autologinGroup = m_config->autologinGroup(); + groupsForThisUser << autologinGroup; + ensureGroupsExistInTarget( QList< GroupDescription >() << GroupDescription( autologinGroup ), availableGroups ); } - ensureGroupsExistInTarget( groupsForThisUser, availableGroups ); // If we're looking to reuse the contents of an existing /home. // This GS setting comes from the **partitioning** module. if ( gs->value( "reuseHome" ).toBool() ) { - QString shellFriendlyHome = "/home/" + m_userName; + QString shellFriendlyHome = "/home/" + m_config->loginName(); QDir existingHome( destDir.absolutePath() + shellFriendlyHome ); if ( existingHome.exists() ) { @@ -216,20 +222,20 @@ CreateUserJob::exec() cDebug() << "[CREATEUSER]: creating user"; - auto useraddResult = createUser( m_userName, m_fullName, gs->value( "userShell" ).toString() ); + auto useraddResult = createUser( m_config->loginName(), m_config->fullName(), m_config->userShell() ); if ( !useraddResult ) { return useraddResult; } - auto usergroupsResult = setUserGroups( m_userName, groupsForThisUser ); + auto usergroupsResult = setUserGroups( m_config->loginName(), groupsForThisUser ); if ( !usergroupsResult ) { return usergroupsResult; } - QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName ); - QString homeDir = QString( "/home/%1" ).arg( m_userName ); + QString userGroup = QString( "%1:%2" ).arg( m_config->loginName() ).arg( m_config->loginName() ); + QString homeDir = QString( "/home/%1" ).arg( m_config->loginName() ); auto commandResult = CalamaresUtils::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } ); if ( commandResult.getExitCode() ) { diff --git a/src/modules/users/CreateUserJob.h b/src/modules/users/CreateUserJob.h index 0a46198b9..0bc140bff 100644 --- a/src/modules/users/CreateUserJob.h +++ b/src/modules/users/CreateUserJob.h @@ -12,23 +12,20 @@ #include "Job.h" -#include +class Config; class CreateUserJob : public Calamares::Job { Q_OBJECT public: - CreateUserJob( const QString& userName, const QString& fullName, bool autologin, const QStringList& defaultGroups ); + CreateUserJob( const Config* config ); QString prettyName() const override; QString prettyDescription() const override; QString prettyStatusMessage() const override; Calamares::JobResult exec() override; private: - QString m_userName; - QString m_fullName; - bool m_autologin; - QStringList m_defaultGroups; + const Config* m_config; }; #endif /* CREATEUSERJOB_H */ From 58f10739e110c42a74670ea62b9262ce4588d3a3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 00:55:00 +0200 Subject: [PATCH 10/72] [users] Show progress during the module - add a status member so the different steps can show progress as the user is created and configured. The progress values are hard-coded guesses as to how much work is done for each step. - while here, reduce the scope of the global storage variable --- src/modules/users/CreateUserJob.cpp | 30 +++++++++++++++++++++++------ src/modules/users/CreateUserJob.h | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index 2bdb6296a..c9830abd4 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -47,7 +47,7 @@ CreateUserJob::prettyDescription() const QString CreateUserJob::prettyStatusMessage() const { - return tr( "Creating user %1." ).arg( m_config->loginName() ); + return m_status.isEmpty() ? tr( "Creating user %1." ).arg( m_config->loginName() ) : m_status; } STATICTEST QStringList @@ -157,14 +157,22 @@ setUserGroups( const QString& loginName, const QStringList& groups ) Calamares::JobResult CreateUserJob::exec() { - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - QDir destDir( gs->value( "rootMountPoint" ).toString() ); + QDir destDir; + bool reuseHome = false; - if ( gs->contains( "sudoersGroup" ) && !gs->value( "sudoersGroup" ).toString().isEmpty() ) { + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + destDir = QDir( gs->value( "rootMountPoint" ).toString() ); + reuseHome = gs->value( "reuseHome" ).toBool(); + } + + if ( !m_config->sudoersGroup().isEmpty() ) + { + m_status = tr( "Preparing sudo for user %1" ).arg( m_config->loginName() ); + emit progress( 0.05 ); cDebug() << "[CREATEUSER]: preparing sudoers"; - QString sudoersLine = QString( "%%1 ALL=(ALL) ALL\n" ).arg( gs->value( "sudoersGroup" ).toString() ); + QString sudoersLine = QString( "%%1 ALL=(ALL) ALL\n" ).arg( m_config->sudoersGroup() ); auto fileResult = CalamaresUtils::System::instance()->createTargetFile( QStringLiteral( "/etc/sudoers.d/10-installer" ), sudoersLine.toUtf8().constData(), @@ -185,6 +193,8 @@ CreateUserJob::exec() cDebug() << "[CREATEUSER]: preparing groups"; + m_status = tr( "Preparing groups for user %1" ).arg( m_config->loginName() ); + emit progress( 0.1 ); // loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), groupNames ); const auto& defaultGroups = m_config->defaultGroups(); QStringList groupsForThisUser = std::accumulate( @@ -205,8 +215,10 @@ CreateUserJob::exec() // If we're looking to reuse the contents of an existing /home. // This GS setting comes from the **partitioning** module. - if ( gs->value( "reuseHome" ).toBool() ) + if ( reuseHome ) { + m_status = tr( "Preserving home directory" ); + emit progress( 0.2 ); QString shellFriendlyHome = "/home/" + m_config->loginName(); QDir existingHome( destDir.absolutePath() + shellFriendlyHome ); if ( existingHome.exists() ) @@ -222,18 +234,24 @@ CreateUserJob::exec() cDebug() << "[CREATEUSER]: creating user"; + m_status = tr( "Creating user %1" ).arg( m_config->loginName() ); + emit progress( 0.5 ); auto useraddResult = createUser( m_config->loginName(), m_config->fullName(), m_config->userShell() ); if ( !useraddResult ) { return useraddResult; } + m_status = tr( "Configuring user %1" ).arg( m_config->loginName() ); + emit progress( 0.8 ); auto usergroupsResult = setUserGroups( m_config->loginName(), groupsForThisUser ); if ( !usergroupsResult ) { return usergroupsResult; } + m_status = tr( "Setting file permissions" ); + emit progress( 0.9 ); QString userGroup = QString( "%1:%2" ).arg( m_config->loginName() ).arg( m_config->loginName() ); QString homeDir = QString( "/home/%1" ).arg( m_config->loginName() ); auto commandResult = CalamaresUtils::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } ); diff --git a/src/modules/users/CreateUserJob.h b/src/modules/users/CreateUserJob.h index 0bc140bff..28a48c886 100644 --- a/src/modules/users/CreateUserJob.h +++ b/src/modules/users/CreateUserJob.h @@ -26,6 +26,7 @@ public: private: const Config* m_config; + QString m_status; }; #endif /* CREATEUSERJOB_H */ From 788a233319a1d5c143351098e9fb5709de0a8700 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 01:10:48 +0200 Subject: [PATCH 11/72] [users] Introduce a test for Config getters and setters --- src/modules/users/Tests.cpp | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 0ffeeae51..e973868db 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -33,6 +33,9 @@ public: private Q_SLOTS: void initTestCase(); + // Derpy test for getting and setting regular values + void testGetSet(); + void testDefaultGroups(); void testDefaultGroupsYAML_data(); void testDefaultGroupsYAML(); @@ -52,6 +55,60 @@ UserTests::initTestCase() cDebug() << "Users test started."; } +void +UserTests::testGetSet() +{ + Config c; + + { + const QString sh( "/bin/sh" ); + QCOMPARE( c.userShell(), QString() ); + c.setUserShell( sh ); + QCOMPARE( c.userShell(), sh ); + c.setUserShell( sh + sh ); + QCOMPARE( c.userShell(), sh + sh ); + + const QString badsh( "bash" ); // Not absolute, that's bad + c.setUserShell( badsh ); + QEXPECT_FAIL( "", "Shell Unchanged", Abort ); + QCOMPARE( c.userShell(), badsh ); + QCOMPARE( c.userShell(), sh + sh ); // what was set previously + + // Explicit set to empty is ok + c.setUserShell( QString() ); + QCOMPARE( c.userShell(), QString() ); + } + { + const QString al( "autolg" ); + QCOMPARE( c.autologinGroup(), QString() ); + c.setAutologinGroup( al ); + QCOMPARE( c.autologinGroup(), al ); + QVERIFY( !c.doAutoLogin() ); + c.setAutoLogin( true ); + QVERIFY( c.doAutoLogin() ); + QCOMPARE( c.autologinGroup(), al ); + } + { + const QString su( "sudogrp" ); + QCOMPARE( c.sudoersGroup(), QString() ); + c.setSudoersGroup( su ); + QCOMPARE( c.sudoersGroup(), su ); + } + { + const QString ful( "Jan-Jaap Karel Kees" ); + const QString lg( "jjkk" ); + QCOMPARE( c.fullName(), QString() ); + QCOMPARE( c.loginName(), QString() ); + QVERIFY( !c.loginNameStatus().isEmpty() ); // login name is not ok + c.setLoginName( lg ); + c.setFullName( ful ); + QVERIFY( c.loginNameStatus().isEmpty() ); // now it's ok + QCOMPARE( c.loginName(), lg ); + QCOMPARE( c.fullName(), ful ); + } +} + + void UserTests::testDefaultGroups() { From 6b2d7f6a4259cf575a5736749bd5789d0bfc7db8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 01:15:16 +0200 Subject: [PATCH 12/72] [users] Protect against JobQueue or GS being NULL - Avoid SIGSEGV in tests, make sure JobQueue exists, GS optional --- src/modules/users/Config.cpp | 5 +++++ src/modules/users/Tests.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index b3d94666a..da57db0fc 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -34,6 +34,11 @@ static void updateGSAutoLogin( bool doAutoLogin, const QString& login ) { Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + if ( !gs ) + { + cWarning() << "No Global Storage available"; + return; + } if ( doAutoLogin && !login.isEmpty() ) { diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index e973868db..3d4aa8694 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -53,6 +53,11 @@ UserTests::initTestCase() { Logger::setupLogLevel( Logger::LOGDEBUG ); cDebug() << "Users test started."; + + if ( !Calamares::JobQueue::instance() ) + { + (void)new Calamares::JobQueue(); + } } void From f726634c2fe6ba668648e961181108e4e0b1c48c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 12:52:47 +0200 Subject: [PATCH 13/72] [users] Fix tests for setting shell - The EXPECT_FAIL value "Abort" stops the test (I wanted 'if this unexpectedly passes, raise an error' -- should have read the documentation more closely). - Set the shell in the config object, not just in GS. --- src/modules/users/Config.cpp | 13 +++++++++---- src/modules/users/Tests.cpp | 4 +--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index da57db0fc..e8d0192ee 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -100,11 +100,16 @@ Config::setUserShell( const QString& shell ) cWarning() << "User shell" << shell << "is not an absolute path."; return; } - // The shell is put into GS because the CreateUser job expects it there - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs ) + if ( shell != m_userShell ) { - gs->insert( "userShell", shell ); + m_userShell = shell; + emit userShellChanged(shell); + // The shell is put into GS as well. + auto* gs = Calamares::JobQueue::instance()->globalStorage(); + if ( gs ) + { + gs->insert( "userShell", shell ); + } } } diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 3d4aa8694..b1ec8ebbc 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -74,9 +74,7 @@ UserTests::testGetSet() QCOMPARE( c.userShell(), sh + sh ); const QString badsh( "bash" ); // Not absolute, that's bad - c.setUserShell( badsh ); - QEXPECT_FAIL( "", "Shell Unchanged", Abort ); - QCOMPARE( c.userShell(), badsh ); + c.setUserShell( badsh ); // .. so unchanged QCOMPARE( c.userShell(), sh + sh ); // what was set previously // Explicit set to empty is ok From 89e279c96ad9af66b36a735d6de8d71bb8718321 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 15:04:37 +0200 Subject: [PATCH 14/72] [users] Set auto- and sudo-groups correctly - Was updating GS only, not internals - restructure all to update internals, then GS, then emit change signals --- src/modules/users/Config.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index e8d0192ee..024661d8d 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -127,15 +127,23 @@ insertInGlobalStorage( const QString& key, const QString& group ) void Config::setAutologinGroup( const QString& group ) { - insertInGlobalStorage( QStringLiteral( "autologinGroup" ), group ); - emit autologinGroupChanged( group ); + if ( group != m_autologinGroup ) + { + m_autologinGroup = group; + insertInGlobalStorage( QStringLiteral( "autologinGroup" ), group ); + emit autologinGroupChanged( group ); + } } void Config::setSudoersGroup( const QString& group ) { - insertInGlobalStorage( QStringLiteral( "sudoersGroup" ), group ); - emit sudoersGroupChanged( group ); + if ( group != m_sudoersGroup ) + { + m_sudoersGroup = group; + insertInGlobalStorage( QStringLiteral( "sudoersGroup" ), group ); + emit sudoersGroupChanged( group ); + } } @@ -144,10 +152,9 @@ Config::setLoginName( const QString& login ) { if ( login != m_loginName ) { - updateGSAutoLogin( doAutoLogin(), login ); - m_customLoginName = !login.isEmpty(); m_loginName = login; + updateGSAutoLogin( doAutoLogin(), login ); emit loginNameChanged( login ); emit loginNameStatusChanged( loginNameStatus() ); } @@ -199,6 +206,8 @@ Config::setHostName( const QString& host ) { if ( host != m_hostName ) { + m_customHostName = !host.isEmpty(); + m_hostName = host; Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); if ( host.isEmpty() ) { @@ -208,9 +217,6 @@ Config::setHostName( const QString& host ) { gs->insert( "hostname", host ); } - - m_customHostName = !host.isEmpty(); - m_hostName = host; emit hostNameChanged( host ); emit hostNameStatusChanged( hostNameStatus() ); } @@ -379,8 +385,8 @@ Config::setAutoLogin( bool b ) { if ( b != m_doAutoLogin ) { - updateGSAutoLogin( b, loginName() ); m_doAutoLogin = b; + updateGSAutoLogin( b, loginName() ); emit autoLoginChanged( b ); } } From 2911c789f928d65307e315aaf2f58dd56d183ba5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 14 Oct 2020 15:15:47 +0200 Subject: [PATCH 15/72] [users] Fix up tests for login status - an empty login name is "ok" even if it isn't -- there's no warning message in that case --- src/modules/users/Tests.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index b1ec8ebbc..5259fb8a8 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -102,12 +102,14 @@ UserTests::testGetSet() const QString lg( "jjkk" ); QCOMPARE( c.fullName(), QString() ); QCOMPARE( c.loginName(), QString() ); - QVERIFY( !c.loginNameStatus().isEmpty() ); // login name is not ok + QVERIFY( c.loginNameStatus().isEmpty() ); // empty login name is ok c.setLoginName( lg ); c.setFullName( ful ); - QVERIFY( c.loginNameStatus().isEmpty() ); // now it's ok + QVERIFY( c.loginNameStatus().isEmpty() ); // now it's still ok QCOMPARE( c.loginName(), lg ); QCOMPARE( c.fullName(), ful ); + c.setLoginName( "root" ); + QVERIFY( !c.loginNameStatus().isEmpty() ); // can't be root } } From 328a5bbbfb693c16e11e203ac98445e2a449c2d8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 17 Oct 2020 15:48:12 +0200 Subject: [PATCH 16/72] [users] Don't allow continuing with an empty login name The status for an empty login name is '' (empty), for ok -- this is so that there is no complaint about it. But it's not ok to continue with an empty name. --- src/modules/users/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index 024661d8d..1216b22a2 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -582,7 +582,7 @@ Config::isReady() const { bool readyFullName = !fullName().isEmpty(); // Needs some text bool readyHostname = hostNameStatus().isEmpty(); // .. no warning message - bool readyUsername = loginNameStatus().isEmpty(); // .. no warning message + bool readyUsername = !loginName().isEmpty() && loginNameStatus().isEmpty(); // .. no warning message bool readyUserPassword = userPasswordValidity() != Config::PasswordValidity::Invalid; bool readyRootPassword = rootPasswordValidity() != Config::PasswordValidity::Invalid; return readyFullName && readyHostname && readyUsername && readyUserPassword && readyRootPassword; From 29e6934672464fa84bca5faa7440919184c8da00 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Oct 2020 14:43:45 +0200 Subject: [PATCH 17/72] [users] Factor out Sudo creation into separate job --- src/modules/users/CMakeLists.txt | 1 + src/modules/users/Config.cpp | 9 ++++- src/modules/users/CreateUserJob.cpp | 25 ------------- src/modules/users/MiscJobs.cpp | 57 +++++++++++++++++++++++++++++ src/modules/users/MiscJobs.h | 34 +++++++++++++++++ 5 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 src/modules/users/MiscJobs.cpp create mode 100644 src/modules/users/MiscJobs.h diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index 5752ae67a..d758e2bb9 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -25,6 +25,7 @@ include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) set( JOB_SRC CreateUserJob.cpp + MiscJobs.cpp SetPasswordJob.cpp SetHostNameJob.cpp ) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index 1216b22a2..dc50f42c5 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -10,6 +10,7 @@ #include "Config.h" #include "CreateUserJob.h" +#include "MiscJobs.h" #include "SetHostNameJob.h" #include "SetPasswordJob.h" @@ -103,7 +104,7 @@ Config::setUserShell( const QString& shell ) if ( shell != m_userShell ) { m_userShell = shell; - emit userShellChanged(shell); + emit userShellChanged( shell ); // The shell is put into GS as well. auto* gs = Calamares::JobQueue::instance()->globalStorage(); if ( gs ) @@ -796,6 +797,12 @@ Config::createJobs() const Calamares::Job* j; + if ( m_sudoersGroup.isEmpty() ) + { + j = new SetupSudoJob( m_sudoersGroup ); + jobs.append( Calamares::job_ptr( j ) ); + } + j = new CreateUserJob( this ); jobs.append( Calamares::job_ptr( j ) ); diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index c9830abd4..efbc4d9e3 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -166,31 +166,6 @@ CreateUserJob::exec() reuseHome = gs->value( "reuseHome" ).toBool(); } - if ( !m_config->sudoersGroup().isEmpty() ) - { - m_status = tr( "Preparing sudo for user %1" ).arg( m_config->loginName() ); - emit progress( 0.05 ); - cDebug() << "[CREATEUSER]: preparing sudoers"; - - QString sudoersLine = QString( "%%1 ALL=(ALL) ALL\n" ).arg( m_config->sudoersGroup() ); - auto fileResult - = CalamaresUtils::System::instance()->createTargetFile( QStringLiteral( "/etc/sudoers.d/10-installer" ), - sudoersLine.toUtf8().constData(), - CalamaresUtils::System::WriteMode::Overwrite ); - - if ( fileResult ) - { - if ( !CalamaresUtils::Permissions::apply( fileResult.path(), 0440 ) ) - { - return Calamares::JobResult::error( tr( "Cannot chmod sudoers file." ) ); - } - } - else - { - return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) ); - } - } - cDebug() << "[CREATEUSER]: preparing groups"; m_status = tr( "Preparing groups for user %1" ).arg( m_config->loginName() ); diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp new file mode 100644 index 000000000..4f9472cc6 --- /dev/null +++ b/src/modules/users/MiscJobs.cpp @@ -0,0 +1,57 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#include "MiscJobs.h" + +#include "Config.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Permissions.h" + +SetupSudoJob::SetupSudoJob( const QString& group ) + : m_sudoGroup( group ) +{ +} + +QString +SetupSudoJob::prettyName() const +{ + return tr( "Configure
sudo
users." ); +} + +Calamares::JobResult +SetupSudoJob::exec() +{ + if ( m_sudoGroup.isEmpty() ) + { + return Calamares::JobResult::ok(); + } + + QString sudoersLine = QString( "%%1 ALL=(ALL) ALL\n" ).arg( m_sudoGroup ); + auto fileResult + = CalamaresUtils::System::instance()->createTargetFile( QStringLiteral( "/etc/sudoers.d/10-installer" ), + sudoersLine.toUtf8().constData(), + CalamaresUtils::System::WriteMode::Overwrite ); + + if ( fileResult ) + { + if ( !CalamaresUtils::Permissions::apply( fileResult.path(), 0440 ) ) + { + return Calamares::JobResult::error( tr( "Cannot chmod sudoers file." ) ); + } + } + else + { + return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) ); + } + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/users/MiscJobs.h b/src/modules/users/MiscJobs.h new file mode 100644 index 000000000..2f8055e8a --- /dev/null +++ b/src/modules/users/MiscJobs.h @@ -0,0 +1,34 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +/**@file Various small jobs + * + * This file collects miscellaneous jobs that need to be run to prepare + * the system for the user-creation job. + */ + +#ifndef USERS_MISCJOBS_H +#define USERS_MISCJOBS_H + +#include "Job.h" + +class SetupSudoJob : public Calamares::Job +{ + Q_OBJECT +public: + SetupSudoJob( const QString& group ); + QString prettyName() const override; + Calamares::JobResult exec() override; + +public: + QString m_sudoGroup; +}; + +#endif From 6560ef00a1bbb38f1a5262e6d67289574b906881 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Oct 2020 14:46:07 +0200 Subject: [PATCH 18/72] [usersq] Fix build of usersq after refactor elsewhere --- src/modules/usersq/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt index 26c270bfb..b6717e7b8 100644 --- a/src/modules/usersq/CMakeLists.txt +++ b/src/modules/usersq/CMakeLists.txt @@ -33,12 +33,13 @@ calamares_add_plugin( usersq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES - ${_users}/Config.cpp - ${_users}/CreateUserJob.cpp + ${_users}/CheckPWQuality.cpp + ${_users}/Config.cpp + ${_users}/CreateUserJob.cpp + ${_users}/MiscJobs.cpp + ${_users}/SetHostNameJob.cpp ${_users}/SetPasswordJob.cpp UsersQmlViewStep.cpp - ${_users}/SetHostNameJob.cpp - ${_users}/CheckPWQuality.cpp RESOURCES usersq.qrc LINK_PRIVATE_LIBRARIES From 3d289f345ad4d175842c2eb1448b9c869ca9c20e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Oct 2020 15:02:33 +0200 Subject: [PATCH 19/72] [users] Refactor users functionality to a static lib - this makes it less fragile to share all the functionality with usersq, since it ends up in the library which is shared between the modules. --- src/modules/users/CMakeLists.txt | 27 ++++++++++++++++++--------- src/modules/users/Config.h | 2 +- src/modules/usersq/CMakeLists.txt | 10 ++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index d758e2bb9..ca5d24d34 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -23,25 +23,35 @@ endif() include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) -set( JOB_SRC +set( _users_src + # Jobs CreateUserJob.cpp MiscJobs.cpp SetPasswordJob.cpp SetHostNameJob.cpp -) -set( CONFIG_SRC + # Configuration CheckPWQuality.cpp Config.cpp ) +calamares_add_library( + users_internal + EXPORT_MACRO PLUGINDLLEXPORT_PRO + TARGET_TYPE STATIC + NO_INSTALL + NO_VERSION + SOURCES + ${_users_src} + LINK_LIBRARIES + Qt5::DBus +) + calamares_add_plugin( users TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES UsersViewStep.cpp UsersPage.cpp - ${JOB_SRC} - ${CONFIG_SRC} UI page_usersetup.ui RESOURCES @@ -50,7 +60,7 @@ calamares_add_plugin( users calamaresui ${CRYPT_LIBRARIES} ${USER_EXTRA_LIB} - Qt5::DBus + users_internal SHARED_LIB ) @@ -83,10 +93,9 @@ calamares_add_test( userstest SOURCES Tests.cpp - ${JOB_SRC} - ${CONFIG_SRC} + ${_users_src} # Build again with test-visibility LIBRARIES ${USER_EXTRA_LIB} - Qt5::DBus # HostName job can use DBus to systemd ${CRYPT_LIBRARIES} # SetPassword job uses crypt() + Qt5::DBus # HostName job can use DBus to systemd ) diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index 04f37d231..57da73e30 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -84,7 +84,7 @@ private: }; -class Config : public QObject +class PLUGINDLLEXPORT Config : public QObject { Q_OBJECT diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt index b6717e7b8..951359c77 100644 --- a/src/modules/usersq/CMakeLists.txt +++ b/src/modules/usersq/CMakeLists.txt @@ -13,9 +13,8 @@ find_package( Crypt REQUIRED ) # Add optional libraries here set( USER_EXTRA_LIB ) -set( _users ${CMAKE_CURRENT_SOURCE_DIR}/../users ) -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ${CMAKE_CURRENT_SOURCE_DIR}/../../libcalamares ${_users} ) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../users ) find_package( LibPWQuality ) set_package_properties( @@ -33,12 +32,6 @@ calamares_add_plugin( usersq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES - ${_users}/CheckPWQuality.cpp - ${_users}/Config.cpp - ${_users}/CreateUserJob.cpp - ${_users}/MiscJobs.cpp - ${_users}/SetHostNameJob.cpp - ${_users}/SetPasswordJob.cpp UsersQmlViewStep.cpp RESOURCES usersq.qrc @@ -47,5 +40,6 @@ calamares_add_plugin( usersq ${CRYPT_LIBRARIES} ${USER_EXTRA_LIB} Qt5::DBus + users_internal SHARED_LIB ) From fa1d314b13fb1f605bf7d29755067bfcc12919eb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Oct 2020 13:49:45 +0200 Subject: [PATCH 20/72] [users] Refactor group-creation into separate Job --- src/modules/users/MiscJobs.cpp | 126 +++++++++++++++++++++++++++++++++ src/modules/users/MiscJobs.h | 16 +++++ 2 files changed, 142 insertions(+) diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp index 4f9472cc6..04880d1d8 100644 --- a/src/modules/users/MiscJobs.cpp +++ b/src/modules/users/MiscJobs.cpp @@ -12,10 +12,16 @@ #include "Config.h" +#include "GlobalStorage.h" +#include "JobQueue.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include "utils/Permissions.h" +#include +#include +#include + SetupSudoJob::SetupSudoJob( const QString& group ) : m_sudoGroup( group ) { @@ -55,3 +61,123 @@ SetupSudoJob::exec() return Calamares::JobResult::ok(); } + +STATICTEST QStringList +groupsInTargetSystem() +{ + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + QDir targetRoot( gs->value( "rootMountPoint" ).toString() ); + + QFileInfo groupsFi( targetRoot.absoluteFilePath( "etc/group" ) ); + QFile groupsFile( groupsFi.absoluteFilePath() ); + if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + return QStringList(); + } + QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() ); + QStringList groupsLines = groupsData.split( '\n' ); + QStringList::iterator it = groupsLines.begin(); + while ( it != groupsLines.end() ) + { + if ( it->startsWith( '#' ) ) + { + it = groupsLines.erase( it ); + continue; + } + int indexOfFirstToDrop = it->indexOf( ':' ); + if ( indexOfFirstToDrop < 1 ) + { + it = groupsLines.erase( it ); + continue; + } + it->truncate( indexOfFirstToDrop ); + ++it; + } + return groupsLines; +} + +/** @brief Create groups in target system as needed + * + * Given a list of groups that already exist, @p availableGroups, + * go through the @p wantedGroups and create each of them. Groups that + * fail, or which should have already been there, are added to + * @p missingGroups by name. + */ +static bool +ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, + const QStringList& availableGroups, + QStringList& missingGroups ) +{ + int failureCount = 0; + + for ( const auto& group : wantedGroups ) + { + int groupaddResult = 0; + if ( group.isValid() && !availableGroups.contains( group.name() ) ) + { + if ( group.mustAlreadyExist() ) + { + // Should have been there already: don't create it + missingGroups.append( group.name() ); + continue; + } + +#ifdef __FreeBSD__ + groupaddResult + = CalamaresUtils::System::instance()->targetEnvCall( { "pw", "groupadd", "-n", group.name() } ); +#else + groupaddResult = CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group.name() } ); +#endif + if ( groupaddResult ) + { + failureCount++; + missingGroups.append( group.name() + QChar( '*' ) ); + } + } + } + if ( !missingGroups.isEmpty() ) + { + cWarning() << "Missing groups in target system (* for groupadd failure):" << Logger::DebugList( missingGroups ); + } + return failureCount == 0; +} + +SetupGroupsJob::SetupGroupsJob( const Config* config, const QString& autologinGroup ) + : m_autologinGroup( autologinGroup ) + , m_config( config ) +{ +} + +QString +SetupGroupsJob::prettyName() const +{ + return tr( "Preparing groups." ); +} + +Calamares::JobResult +SetupGroupsJob::exec() +{ + const auto& defaultGroups = m_config->defaultGroups(); + QStringList availableGroups = groupsInTargetSystem(); + QStringList missingGroups; + + if ( !ensureGroupsExistInTarget( defaultGroups, availableGroups, missingGroups ) ) + { + return Calamares::JobResult::error( tr( "Could not create groups in target system" ) ); + } + if ( !missingGroups.isEmpty() ) + { + return Calamares::JobResult::error( + tr( "Could not create groups in target system" ), + tr( "These groups are missing in the target system: %1" ).arg( missingGroups.join( ',' ) ) ); + } + + if ( m_config->doAutoLogin() && !m_config->autologinGroup().isEmpty() ) + { + const QString autologinGroup = m_config->autologinGroup(); + (void)ensureGroupsExistInTarget( + QList< GroupDescription >() << GroupDescription( autologinGroup ), availableGroups, missingGroups ); + } + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/users/MiscJobs.h b/src/modules/users/MiscJobs.h index 2f8055e8a..8065079ce 100644 --- a/src/modules/users/MiscJobs.h +++ b/src/modules/users/MiscJobs.h @@ -19,6 +19,8 @@ #include "Job.h" +class Config; + class SetupSudoJob : public Calamares::Job { Q_OBJECT @@ -31,4 +33,18 @@ public: QString m_sudoGroup; }; +class SetupGroupsJob : public Calamares::Job +{ + Q_OBJECT + +public: + SetupGroupsJob( const Config* config, const QString& autologinGroup ); + QString prettyName() const override; + Calamares::JobResult exec() override; + +public: + QString m_autologinGroup; + const Config* m_config; +}; + #endif From 03541470d53c63504ea6609217c1f98ba6078b18 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Oct 2020 14:07:40 +0200 Subject: [PATCH 21/72] [users] Handle system-group creating specially --- src/modules/users/Config.cpp | 18 ++++++++++++++++++ src/modules/users/Config.h | 6 ++++++ src/modules/users/MiscJobs.cpp | 18 +++++++++++++----- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index dc50f42c5..fff6e3960 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -136,6 +136,24 @@ Config::setAutologinGroup( const QString& group ) } } +QStringList +Config::groupsForThisUser() const +{ + QStringList l; + l.reserve( defaultGroups().size() + 1 ); + + for ( const auto& g : defaultGroups() ) + { + l << g.name(); + } + if ( doAutoLogin() && !autologinGroup().isEmpty() ) + { + l << autologinGroup(); + } + + return l; +} + void Config::setSudoersGroup( const QString& group ) { diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h index 57da73e30..d4bfee4a4 100644 --- a/src/modules/users/Config.h +++ b/src/modules/users/Config.h @@ -68,6 +68,7 @@ public: bool isValid() const { return m_isValid; } bool isSystemGroup() const { return m_isSystem; } + bool mustAlreadyExist() const { return m_mustAlreadyExist; } QString name() const { return m_name; } ///@brief Equality of groups depends only on name and kind @@ -213,6 +214,11 @@ public: bool requireStrongPasswords() const { return m_requireStrongPasswords; } const QList< GroupDescription >& defaultGroups() const { return m_defaultGroups; } + /** @brief the names of all the groups for the current user + * + * Takes into account defaultGroups and autologin behavior. + */ + QStringList groupsForThisUser() const; // The user enters a password (and again in a separate UI element) QString userPassword() const { return m_userPassword; } diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp index 04880d1d8..b6fbe55db 100644 --- a/src/modules/users/MiscJobs.cpp +++ b/src/modules/users/MiscJobs.cpp @@ -112,7 +112,6 @@ ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, for ( const auto& group : wantedGroups ) { - int groupaddResult = 0; if ( group.isValid() && !availableGroups.contains( group.name() ) ) { if ( group.mustAlreadyExist() ) @@ -122,13 +121,22 @@ ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, continue; } + QStringList cmd; #ifdef __FreeBSD__ - groupaddResult - = CalamaresUtils::System::instance()->targetEnvCall( { "pw", "groupadd", "-n", group.name() } ); + if ( group.isSystemGroup() ) + { + cWarning() << "Ignoring must-be-a-system group for" << group.name() << "on FreeBSD"; + } + cmd = QStringList { "pw", "groupadd", "-n", group.name() }; #else - groupaddResult = CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group.name() } ); + cmd << QStringLiteral( "groupadd" ); + if ( group.isSystemGroup() ) + { + cmd << "--system"; + } + cmd << group.name(); #endif - if ( groupaddResult ) + if ( CalamaresUtils::System::instance()->targetEnvCall( cmd ) ) { failureCount++; missingGroups.append( group.name() + QChar( '*' ) ); From f1772a7eae565ab8dc474c8b0d58fa889d80b152 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Oct 2020 14:11:01 +0200 Subject: [PATCH 22/72] [users] Create groups in a separate job --- src/modules/users/Config.cpp | 3 ++ src/modules/users/CreateUserJob.cpp | 71 +---------------------------- src/modules/users/MiscJobs.cpp | 5 +- src/modules/users/MiscJobs.h | 3 +- 4 files changed, 7 insertions(+), 75 deletions(-) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index fff6e3960..0e70cc215 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -821,6 +821,9 @@ Config::createJobs() const jobs.append( Calamares::job_ptr( j ) ); } + j = new SetupGroupsJob( this ); + jobs.append( Calamares::job_ptr( j ) ); + j = new CreateUserJob( this ); jobs.append( Calamares::job_ptr( j ) ); diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index efbc4d9e3..e08108a46 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -50,53 +50,6 @@ CreateUserJob::prettyStatusMessage() const return m_status.isEmpty() ? tr( "Creating user %1." ).arg( m_config->loginName() ) : m_status; } -STATICTEST QStringList -groupsInTargetSystem( const QDir& targetRoot ) -{ - QFileInfo groupsFi( targetRoot.absoluteFilePath( "etc/group" ) ); - QFile groupsFile( groupsFi.absoluteFilePath() ); - if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - return QStringList(); - } - QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() ); - QStringList groupsLines = groupsData.split( '\n' ); - QStringList::iterator it = groupsLines.begin(); - while ( it != groupsLines.end() ) - { - if ( it->startsWith( '#' ) ) - { - it = groupsLines.erase( it ); - continue; - } - int indexOfFirstToDrop = it->indexOf( ':' ); - if ( indexOfFirstToDrop < 1 ) - { - it = groupsLines.erase( it ); - continue; - } - it->truncate( indexOfFirstToDrop ); - ++it; - } - return groupsLines; -} - -static void -ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, const QStringList& availableGroups ) -{ - for ( const auto& group : wantedGroups ) - { - if ( group.isValid() && !availableGroups.contains( group.name() ) ) - { -#ifdef __FreeBSD__ - CalamaresUtils::System::instance()->targetEnvCall( { "pw", "groupadd", "-n", group.name() } ); -#else - CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group.name() } ); -#endif - } - } -} - static Calamares::JobResult createUser( const QString& loginName, const QString& fullName, const QString& shell ) { @@ -166,28 +119,6 @@ CreateUserJob::exec() reuseHome = gs->value( "reuseHome" ).toBool(); } - cDebug() << "[CREATEUSER]: preparing groups"; - - m_status = tr( "Preparing groups for user %1" ).arg( m_config->loginName() ); - emit progress( 0.1 ); - // loginName(), fullName().isEmpty() ? loginName() : fullName(), doAutoLogin(), groupNames ); - const auto& defaultGroups = m_config->defaultGroups(); - QStringList groupsForThisUser = std::accumulate( - defaultGroups.begin(), - defaultGroups.end(), - QStringList(), - []( const QStringList& l, const GroupDescription& g ) { return QStringList( l ) << g.name(); } ); - - QStringList availableGroups = groupsInTargetSystem( destDir ); - ensureGroupsExistInTarget( defaultGroups, availableGroups ); - - if ( m_config->doAutoLogin() && !m_config->autologinGroup().isEmpty() ) - { - const QString autologinGroup = m_config->autologinGroup(); - groupsForThisUser << autologinGroup; - ensureGroupsExistInTarget( QList< GroupDescription >() << GroupDescription( autologinGroup ), availableGroups ); - } - // If we're looking to reuse the contents of an existing /home. // This GS setting comes from the **partitioning** module. if ( reuseHome ) @@ -219,7 +150,7 @@ CreateUserJob::exec() m_status = tr( "Configuring user %1" ).arg( m_config->loginName() ); emit progress( 0.8 ); - auto usergroupsResult = setUserGroups( m_config->loginName(), groupsForThisUser ); + auto usergroupsResult = setUserGroups( m_config->loginName(), m_config->groupsForThisUser() ); if ( !usergroupsResult ) { return usergroupsResult; diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp index b6fbe55db..4f2570a0a 100644 --- a/src/modules/users/MiscJobs.cpp +++ b/src/modules/users/MiscJobs.cpp @@ -150,9 +150,8 @@ ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, return failureCount == 0; } -SetupGroupsJob::SetupGroupsJob( const Config* config, const QString& autologinGroup ) - : m_autologinGroup( autologinGroup ) - , m_config( config ) +SetupGroupsJob::SetupGroupsJob( const Config* config ) + : m_config( config ) { } diff --git a/src/modules/users/MiscJobs.h b/src/modules/users/MiscJobs.h index 8065079ce..fe4ff87c0 100644 --- a/src/modules/users/MiscJobs.h +++ b/src/modules/users/MiscJobs.h @@ -38,12 +38,11 @@ class SetupGroupsJob : public Calamares::Job Q_OBJECT public: - SetupGroupsJob( const Config* config, const QString& autologinGroup ); + SetupGroupsJob( const Config* config ); QString prettyName() const override; Calamares::JobResult exec() override; public: - QString m_autologinGroup; const Config* m_config; }; From 5b4f9d0b98ff6e0e71dad47b9afc00921c8d6e80 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Oct 2020 14:21:14 +0200 Subject: [PATCH 23/72] [users] Adjust tests for changed API --- src/modules/users/CMakeLists.txt | 6 +++--- src/modules/users/TestCreateUserJob.cpp | 21 +++++++++------------ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index ca5d24d34..8680de73b 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -74,10 +74,10 @@ calamares_add_test( ) calamares_add_test( - userscreatetest + usersgroupstest SOURCES - TestCreateUserJob.cpp - CreateUserJob.cpp + TestCreateUserJob.cpp # Misnomer + MiscJobs.cpp ) calamares_add_test( diff --git a/src/modules/users/TestCreateUserJob.cpp b/src/modules/users/TestCreateUserJob.cpp index fc2d74dcd..11bdfaa01 100644 --- a/src/modules/users/TestCreateUserJob.cpp +++ b/src/modules/users/TestCreateUserJob.cpp @@ -15,14 +15,14 @@ #include // Implementation details -extern QStringList groupsInTargetSystem( const QDir& targetRoot ); // CreateUserJob +extern QStringList groupsInTargetSystem(); // CreateUserJob -class CreateUserTests : public QObject +class GroupTests : public QObject { Q_OBJECT public: - CreateUserTests(); - ~CreateUserTests() override {} + GroupTests(); + ~GroupTests() override {} private Q_SLOTS: void initTestCase(); @@ -30,23 +30,20 @@ private Q_SLOTS: void testReadGroup(); }; -CreateUserTests::CreateUserTests() {} +GroupTests::GroupTests() {} void -CreateUserTests::initTestCase() +GroupTests::initTestCase() { Logger::setupLogLevel( Logger::LOGDEBUG ); cDebug() << "Users test started."; } void -CreateUserTests::testReadGroup() +GroupTests::testReadGroup() { - QDir root( "/" ); - QVERIFY( root.exists() ); - // Get the groups in the host system - QStringList groups = groupsInTargetSystem( root ); + QStringList groups = groupsInTargetSystem(); QVERIFY( groups.count() > 2 ); #ifdef __FreeBSD__ QVERIFY( groups.contains( QStringLiteral( "wheel" ) ) ); @@ -65,7 +62,7 @@ CreateUserTests::testReadGroup() } } -QTEST_GUILESS_MAIN( CreateUserTests ) +QTEST_GUILESS_MAIN( GroupTests ) #include "utils/moc-warnings.h" From 89d495d5fb914fe6e3810fd9f3a053c207aa0782 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Oct 2020 14:22:11 +0200 Subject: [PATCH 24/72] [users] Rename file to match its purpose --- src/modules/users/CMakeLists.txt | 2 +- .../users/{TestCreateUserJob.cpp => TestGroupInformation.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/modules/users/{TestCreateUserJob.cpp => TestGroupInformation.cpp} (100%) diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index 8680de73b..34a0f6856 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -76,7 +76,7 @@ calamares_add_test( calamares_add_test( usersgroupstest SOURCES - TestCreateUserJob.cpp # Misnomer + TestGroupInformation.cpp MiscJobs.cpp ) diff --git a/src/modules/users/TestCreateUserJob.cpp b/src/modules/users/TestGroupInformation.cpp similarity index 100% rename from src/modules/users/TestCreateUserJob.cpp rename to src/modules/users/TestGroupInformation.cpp From cd8c3089cbfa1f2b4d3a1ef85189f0fc162596a1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Oct 2020 11:14:59 +0200 Subject: [PATCH 25/72] [users] Fix build: renamed moc file --- src/modules/users/TestGroupInformation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp index 11bdfaa01..3a04409d5 100644 --- a/src/modules/users/TestGroupInformation.cpp +++ b/src/modules/users/TestGroupInformation.cpp @@ -66,4 +66,4 @@ QTEST_GUILESS_MAIN( GroupTests ) #include "utils/moc-warnings.h" -#include "TestCreateUserJob.moc" +#include "TestGroupInformation.moc" From 63196ab58fc09b71163ec5ecd0e0f5c82dd3d180 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Oct 2020 12:19:28 +0200 Subject: [PATCH 26/72] [users] Avoid crashes in tests due to nullptr GS --- src/modules/users/MiscJobs.cpp | 4 ++++ src/modules/users/TestGroupInformation.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp index 4f2570a0a..a62ada6d7 100644 --- a/src/modules/users/MiscJobs.cpp +++ b/src/modules/users/MiscJobs.cpp @@ -66,6 +66,10 @@ STATICTEST QStringList groupsInTargetSystem() { Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + if ( !gs ) + { + return QStringList(); + } QDir targetRoot( gs->value( "rootMountPoint" ).toString() ); QFileInfo groupsFi( targetRoot.absoluteFilePath( "etc/group" ) ); diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp index 3a04409d5..6f650049a 100644 --- a/src/modules/users/TestGroupInformation.cpp +++ b/src/modules/users/TestGroupInformation.cpp @@ -9,6 +9,7 @@ #include "CreateUserJob.h" +#include "JobQueue.h" #include "utils/Logger.h" #include @@ -37,6 +38,10 @@ GroupTests::initTestCase() { Logger::setupLogLevel( Logger::LOGDEBUG ); cDebug() << "Users test started."; + if ( !Calamares::JobQueue::instance() ) + { + (void)new Calamares::JobQueue(); + } } void From 0d4d3e3c4d14ad86bd2c27a9dcb3f720660c7ab2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Oct 2020 12:27:44 +0200 Subject: [PATCH 27/72] [users] Set up GS rootMountPoint for test --- src/modules/users/TestGroupInformation.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp index 6f650049a..3b2046bda 100644 --- a/src/modules/users/TestGroupInformation.cpp +++ b/src/modules/users/TestGroupInformation.cpp @@ -9,6 +9,7 @@ #include "CreateUserJob.h" +#include "GlobalStorage.h" #include "JobQueue.h" #include "utils/Logger.h" @@ -47,6 +48,7 @@ GroupTests::initTestCase() void GroupTests::testReadGroup() { + Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); // Get the groups in the host system QStringList groups = groupsInTargetSystem(); QVERIFY( groups.count() > 2 ); From dad9587c3ea7ddceddd8b2dc08be8b49fdbb1f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Tue, 27 Oct 2020 07:16:39 -0400 Subject: [PATCH 28/72] [partition] Allow a configurable swap Partition name This commit adds the new configuration `swapPartitionName` to the file partition.conf. This option sets the partition name to the swap partition that is created. If this option is unset, the partition is left unnamed. --- src/modules/partition/core/PartitionActions.cpp | 4 ++++ src/modules/partition/gui/PartitionViewStep.cpp | 6 ++++++ src/modules/partition/partition.conf | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index a78e8ff53..c874145e3 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -203,6 +203,10 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO KPM_PARTITION_FLAG( None ) ); } PartitionInfo::setFormat( swapPartition, true ); + if ( gs->contains( "swapPartitionName" )) + { + swapPartition->setLabel( gs->value( "swapPartitionName" ).toString() ); + } core->createPartition( dev, swapPartition ); } diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 0431e1107..13f5e77cc 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -543,6 +543,12 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) ); } + // Read and parse key swapPartitionName + if ( configurationMap.contains( "swapPartitionName" ) ) + { + gs->insert( "swapPartitionName", CalamaresUtils::getString( configurationMap, "swapPartitionName" ) ); + } + // OTHER SETTINGS // gs->insert( "drawNestedPartitions", CalamaresUtils::getBool( configurationMap, "drawNestedPartitions", false ) ); diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 0f8764bfd..95f7d0576 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -48,6 +48,10 @@ userSwapChoices: # - reuse # Re-use existing swap, but don't create any (unsupported right now) - file # To swap file instead of partition +# This optional setting specifies the name of the swap partition. +# If nothing is specified, the partition name is left unset. +# swapPartitionName: swap + # LEGACY SETTINGS (these will generate a warning) # ensureSuspendToDisk: true # neverCreateSwap: false From a1d45122ebe6a36a185c2dc52b8267562a973a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 31 Oct 2020 17:53:11 -0400 Subject: [PATCH 29/72] [partition] Update partition.conf --- src/modules/partition/partition.conf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 95f7d0576..41652fe7d 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -12,7 +12,8 @@ efiSystemPartition: "/boot/efi" # If nothing is specified, the default size of 300MiB will be used. # efiSystemPartitionSize: 300M -# This optional setting specifies the name of the EFI system partition. +# This optional setting specifies the name of the EFI system partition (see +# PARTLABEL; gpt only; requires KPMCore >= 4.2.0). # If nothing is specified, the partition name is left unset. # efiSystemPartitionName: EFI @@ -48,7 +49,8 @@ userSwapChoices: # - reuse # Re-use existing swap, but don't create any (unsupported right now) - file # To swap file instead of partition -# This optional setting specifies the name of the swap partition. +# This optional setting specifies the name of the swap partition (see +# PARTLABEL; gpt only; requires KPMCore >= 4.2.0). # If nothing is specified, the partition name is left unset. # swapPartitionName: swap From 3967cfe0ebcccba1b392b96930090965093663cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Tue, 27 Oct 2020 09:59:18 -0400 Subject: [PATCH 30/72] [partition] Group EFI things together --- .../partition/core/PartitionActions.cpp | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index a78e8ff53..5207d8947 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -97,21 +97,6 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // empty and a EFI boot partition, while BIOS starts at // the 1MiB boundary (usually sector 2048). int empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; - int uefisys_part_sizeB = 0_MiB; - - if ( isEfi ) - { - if ( gs->contains( "efiSystemPartitionSize" ) ) - { - CalamaresUtils::Partition::PartitionSize part_size - = CalamaresUtils::Partition::PartitionSize( gs->value( "efiSystemPartitionSize" ).toString() ); - uefisys_part_sizeB = part_size.toBytes( dev->capacity() ); - } - else - { - uefisys_part_sizeB = 300_MiB; - } - } // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors @@ -128,6 +113,14 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO if ( isEfi ) { + int uefisys_part_sizeB = 300_MiB; + if ( gs->contains( "efiSystemPartitionSize" ) ) + { + CalamaresUtils::Partition::PartitionSize part_size + = CalamaresUtils::Partition::PartitionSize( gs->value( "efiSystemPartitionSize" ).toString() ); + uefisys_part_sizeB = part_size.toBytes( dev->capacity() ); + } + qint64 efiSectorCount = CalamaresUtils::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); Q_ASSERT( efiSectorCount > 0 ); From 0bad5469fc82e938ca8aaf5510a6cb4de463bd39 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 1 Nov 2020 17:59:41 +0100 Subject: [PATCH 31/72] [libcalamares] Fix tests failures from JobQueue asserts Some compile flags changed recently, triggering assert() in the jobqueue when there is more than one. There's no real reason for JobQueue to be a singleton, but it wants to be. So clean up pointers a little more enthusiastically. --- src/libcalamares/JobQueue.cpp | 1 + src/modules/partition/tests/CreateLayoutsTests.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index 1637f0719..b66be7ebe 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -249,6 +249,7 @@ JobQueue::~JobQueue() } delete m_storage; + s_instance = nullptr; } diff --git a/src/modules/partition/tests/CreateLayoutsTests.cpp b/src/modules/partition/tests/CreateLayoutsTests.cpp index fb991fc82..4b76bb83a 100644 --- a/src/modules/partition/tests/CreateLayoutsTests.cpp +++ b/src/modules/partition/tests/CreateLayoutsTests.cpp @@ -25,6 +25,7 @@ class SmartStatus; QTEST_GUILESS_MAIN( CreateLayoutsTests ) static CalamaresUtils::Partition::KPMManager* kpmcore = nullptr; +static Calamares::JobQueue* jobqueue = nullptr; using CalamaresUtils::operator""_MiB; using CalamaresUtils::operator""_GiB; @@ -39,7 +40,7 @@ CreateLayoutsTests::CreateLayoutsTests() void CreateLayoutsTests::init() { - std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); + jobqueue = new Calamares::JobQueue( nullptr ); kpmcore = new CalamaresUtils::Partition::KPMManager(); } @@ -47,6 +48,7 @@ void CreateLayoutsTests::cleanup() { delete kpmcore; + delete jobqueue; } void From e66f81f6ee132a707d0ab2dc26afb9cd41dbe7db Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 12:01:02 +0100 Subject: [PATCH 32/72] CMake: comment on BUILD_AS_TEST --- CMakeModules/CalamaresAddTest.cmake | 2 ++ src/modules/users/Tests.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/CMakeModules/CalamaresAddTest.cmake b/CMakeModules/CalamaresAddTest.cmake index 56a45d7dc..228d7cbc0 100644 --- a/CMakeModules/CalamaresAddTest.cmake +++ b/CMakeModules/CalamaresAddTest.cmake @@ -42,6 +42,8 @@ function( calamares_add_test ) Qt5::Test ) calamares_automoc( ${TEST_NAME} ) + # We specifically pass in the source directory of the test-being- + # compiled, so that it can find test-files in that source dir. target_compile_definitions( ${TEST_NAME} PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS} ) if( TEST_GUI ) target_link_libraries( ${TEST_NAME} calamaresui Qt5::Gui ) diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index 5259fb8a8..b687a6434 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -196,6 +196,7 @@ UserTests::testDefaultGroupsYAML() QFETCH( int, count ); QFETCH( QString, group ); + // BUILD_AS_TEST is the source-directory path QFile fi( QString( "%1/%2" ).arg( BUILD_AS_TEST, filename ) ); QVERIFY( fi.exists() ); From 8127ae704ca93a0fc2fb92106ea6bd456f993c17 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 12:11:13 +0100 Subject: [PATCH 33/72] [users] Expand tests for groups a little --- src/modules/users/CMakeLists.txt | 6 ++++- src/modules/users/TestGroupInformation.cpp | 28 +++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index f2cb011f4..8b8e87080 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -77,7 +77,11 @@ calamares_add_test( usersgroupstest SOURCES TestGroupInformation.cpp - MiscJobs.cpp + ${_users_src} # Build again with test-visibility + LIBRARIES + Qt5::DBus # HostName job can use DBus to systemd + ${CRYPT_LIBRARIES} # SetPassword job uses crypt() + ${USER_EXTRA_LIB} ) calamares_add_test( diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp index 3b2046bda..5e8bcf9ab 100644 --- a/src/modules/users/TestGroupInformation.cpp +++ b/src/modules/users/TestGroupInformation.cpp @@ -7,11 +7,14 @@ * */ +#include "Config.h" #include "CreateUserJob.h" +#include "MiscJobs.h" #include "GlobalStorage.h" #include "JobQueue.h" #include "utils/Logger.h" +#include "utils/Yaml.h" #include #include @@ -30,6 +33,7 @@ private Q_SLOTS: void initTestCase(); void testReadGroup(); + void testCreateGroup(); }; GroupTests::GroupTests() {} @@ -43,12 +47,12 @@ GroupTests::initTestCase() { (void)new Calamares::JobQueue(); } + Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); } void GroupTests::testReadGroup() { - Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); // Get the groups in the host system QStringList groups = groupsInTargetSystem(); QVERIFY( groups.count() > 2 ); @@ -69,6 +73,28 @@ GroupTests::testReadGroup() } } +void GroupTests::testCreateGroup() +{ + Config g; + + // BUILD_AS_TEST is the source-directory path + QFile fi( QString( "%1/tests/5-issue-1523.conf" ).arg( BUILD_AS_TEST ) ); + QVERIFY( fi.exists() ); + + bool ok = false; + const auto map = CalamaresUtils::loadYaml( fi, &ok ); + QVERIFY( ok ); + QVERIFY( map.count() > 0 ); // Just that it loaded, one key *defaultGroups* + + Config c; + c.setConfigurationMap( map ); + + QCOMPARE( c.defaultGroups().count(), 4 ); + QVERIFY( c.defaultGroups().contains( QStringLiteral( "adm" ) ) ); +} + + + QTEST_GUILESS_MAIN( GroupTests ) #include "utils/moc-warnings.h" From b61b5f8650bdb3f4b57d997baa20715e115ded28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 12:27:50 +0100 Subject: [PATCH 34/72] [users] Run an expected-to-fail test in creating groups --- src/modules/users/TestGroupInformation.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp index 5e8bcf9ab..dd4bfe78f 100644 --- a/src/modules/users/TestGroupInformation.cpp +++ b/src/modules/users/TestGroupInformation.cpp @@ -75,8 +75,6 @@ GroupTests::testReadGroup() void GroupTests::testCreateGroup() { - Config g; - // BUILD_AS_TEST is the source-directory path QFile fi( QString( "%1/tests/5-issue-1523.conf" ).arg( BUILD_AS_TEST ) ); QVERIFY( fi.exists() ); @@ -91,6 +89,12 @@ void GroupTests::testCreateGroup() QCOMPARE( c.defaultGroups().count(), 4 ); QVERIFY( c.defaultGroups().contains( QStringLiteral( "adm" ) ) ); + QVERIFY( c.defaultGroups().contains( QStringLiteral( "bar" ) ) ); + + Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); + + SetupGroupsJob j(&c); + QVERIFY( !j.exec() ); // running as regular user this should fail } From 486cdaeeb6923a5819023ae18bf58e6c7afeec35 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 14:10:35 +0100 Subject: [PATCH 35/72] [users] Shuffle library order to satisfy CI build --- CHANGES | 6 ++++-- src/modules/users/CMakeLists.txt | 3 ++- src/modules/usersq/CMakeLists.txt | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 73c99cf9b..85accf44d 100644 --- a/CHANGES +++ b/CHANGES @@ -20,12 +20,14 @@ This release contains contributions from (alphabetically by first name): - Calamares now sets the C++ standard for compilation to C++17; this is for better compatibility and fewer warnings when building with modern KDE Frameworks and KPMcore 4.2.0. - - Vietnamese translations have been added. Welcome! + - Vietnamese translations have been added. Welcome! (Thanks TTran) ## Modules ## - The *keyboard* and *keyboardq* modules now share backend code and handle non-ASCII layouts better (for setting passwords - and usernames). + and usernames). (Thanks Artem) + - Various cleanups and documentation improvements in the *partition* + module, and configurable GPT name for swap. (Thanks Gaël) # 3.2.32.1 (2020-10-17) # diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index 8b8e87080..92a9e03e7 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -44,6 +44,7 @@ calamares_add_library( ${_users_src} LINK_LIBRARIES Qt5::DBus + ${CRYPT_LIBRARIES} ) calamares_add_plugin( users @@ -57,10 +58,10 @@ calamares_add_plugin( users RESOURCES users.qrc LINK_PRIVATE_LIBRARIES + users_internal calamaresui ${CRYPT_LIBRARIES} ${USER_EXTRA_LIB} - users_internal SHARED_LIB ) diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt index 951359c77..7e3fffb8d 100644 --- a/src/modules/usersq/CMakeLists.txt +++ b/src/modules/usersq/CMakeLists.txt @@ -36,10 +36,10 @@ calamares_add_plugin( usersq RESOURCES usersq.qrc LINK_PRIVATE_LIBRARIES + users_internal calamaresui ${CRYPT_LIBRARIES} ${USER_EXTRA_LIB} Qt5::DBus - users_internal SHARED_LIB ) From 1f9f506a16e26d6e41bad65fadb2cfdca47d5a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Wed, 17 Jun 2020 14:16:20 -0400 Subject: [PATCH 36/72] [partition] Make mountPoint optional Some devices cannot be mounted (as DM_verity_hash), therefore, it is nosense to set a mountPoint for them. --- src/modules/partition/core/PartitionLayout.cpp | 3 +-- src/modules/partition/partition.conf | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 15b18da93..0b0c7bedf 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -134,8 +134,7 @@ PartitionLayout::init( 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( "filesystem" ) || !pentry.contains( "size" ) ) { cError() << "Partition layout entry #" << config.indexOf( r ) << "lacks mandatory attributes, switching to default layout."; diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 41652fe7d..ed2719ca7 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -208,7 +208,7 @@ defaultFileSystemType: "ext4" # - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - filesystem: filesystem type -# - mountPoint: partition mount point +# - mountPoint: partition mount point (optional parameter; not mounted if unset) # - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB) # or # % of the available drive space if a '%' is appended to the value From 54fd1f4b260fce83921116d93dd0c83848983e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 31 Oct 2020 04:44:49 -0400 Subject: [PATCH 37/72] [mount] Print a warning if mount failure The return of the call to libcalamares.utils.mount is never tested and it may fail silently; this causes some mounpoints to be missing. This adds a warning if mountpoint cannot be mounted. chcon: failed to get security context of '/tmp/verity': Operation not supported 06:44:23 [6]: static CalamaresUtils::ProcessResult CalamaresUtils::System::runCommand(CalamaresUtils::System::RunLocation, const QStringList&, const QString&, const QString&, std::chrono::seconds) Running "env" ("mount", "-t", "unformatted", "/dev/sdb2", "/tmp/calamares-root-kv8dqgb5/tmp/verity") .. Finished. Exit code: 32 .. Target cmd: ("mount", "-t", "unformatted", "/dev/sdb7", "/tmp/calamares-root-kv8dqgb5/tmp/verity") output: mount: /tmp/calamares-root-kv8dqgb5/tmp/verity: unknown filesystem type 'unformatted'. --- src/modules/mount/main.py | 71 ++++++++++++++------------------------- 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 01c0650bf..5ef7a2734 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -7,6 +7,7 @@ # SPDX-FileCopyrightText: 2017 Alf Gaida # SPDX-FileCopyrightText: 2019 Adriaan de Groot # SPDX-FileCopyrightText: 2019 Kevin Kofler +# SPDX-FileCopyrightText: 2019-2020 Collabora Ltd # SPDX-License-Identifier: GPL-3.0-or-later # # Calamares is Free Software: see the License-Identifier above. @@ -56,22 +57,16 @@ def mount_partition(root_mount_point, partition, partitions): if fstype == "fat16" or fstype == "fat32": fstype = "vfat" - if "luksMapperName" in partition: - libcalamares.utils.debug( - "about to mount {!s}".format(partition["luksMapperName"])) - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - mount_point, - fstype, - partition.get("options", ""), - ) + device = partition["device"] - else: - libcalamares.utils.mount(partition["device"], - mount_point, - fstype, - partition.get("options", ""), - ) + if "luksMapperName" in partition: + device = os.path.join("/dev/mapper", partition["luksMapperName"]) + + if libcalamares.utils.mount(device, + mount_point, + fstype, + partition.get("options", "")) != 0: + libcalamares.utils.warning("Cannot mount {}".format(device)) # If the root partition is btrfs, we create a subvolume "@" # for the root mount point. @@ -96,37 +91,23 @@ def mount_partition(root_mount_point, partition, partitions): subprocess.check_call(["umount", "-v", root_mount_point]) + device = partition["device"] + if "luksMapperName" in partition: - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - mount_point, - fstype, - ",".join( - ["subvol=@", partition.get("options", "")]), - ) - if not has_home_mount_point: - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - root_mount_point + "/home", - fstype, - ",".join( - ["subvol=@home", partition.get("options", "")]), - ) - else: - libcalamares.utils.mount( - partition["device"], - mount_point, - fstype, - ",".join(["subvol=@", partition.get("options", "")]), - ) - if not has_home_mount_point: - libcalamares.utils.mount( - partition["device"], - root_mount_point + "/home", - fstype, - ",".join( - ["subvol=@home", partition.get("options", "")]), - ) + device = os.path.join("/dev/mapper", partition["luksMapperName"]) + + if libcalamares.utils.mount(device, + mount_point, + fstype, + ",".join(["subvol=@", partition.get("options", "")])) != 0: + libcalamares.utils.warning("Cannot mount {}".format(device)) + + if not has_home_mount_point: + if libcalamares.utils.mount(device, + root_mount_point + "/home", + fstype, + ",".join(["subvol=@home", partition.get("options", "")])) != 0: + libcalamares.utils.warning("Cannot mount {}".format(device)) def run(): From c6feedf9230730ce62d80677fe89ff898495f977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 31 Oct 2020 07:18:30 -0400 Subject: [PATCH 38/72] [mount] Ignore empty mountpoints --- src/modules/mount/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 5ef7a2734..2e4de44fa 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -39,6 +39,9 @@ def mount_partition(root_mount_point, partition, partitions): # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. raw_mount_point = partition["mountPoint"] + if not raw_mount_point: + return + mount_point = root_mount_point + raw_mount_point # Ensure that the created directory has the correct SELinux context on From 163351a803dc4b86d0ac21e0f74d2877fb885b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 31 Oct 2020 07:19:53 -0400 Subject: [PATCH 39/72] [mount] Ignore empty or unformatted filesystems --- src/modules/mount/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 2e4de44fa..71599a6de 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -56,6 +56,8 @@ def mount_partition(root_mount_point, partition, partitions): raise fstype = partition.get("fs", "").lower() + if not fstype or fstype == "unformatted": + return if fstype == "fat16" or fstype == "fat32": fstype = "vfat" From db08d2db8ba31f183d5a538fd838e8b318b18842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 31 Oct 2020 08:09:13 -0400 Subject: [PATCH 40/72] [partition] Make filesystem optional and default to unformatted --- src/modules/partition/core/PartitionLayout.cpp | 4 ++-- src/modules/partition/partition.conf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 0b0c7bedf..4650449bf 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -134,7 +134,7 @@ PartitionLayout::init( const QVariantList& config ) { QVariantMap pentry = r.toMap(); - if ( !pentry.contains( "name" ) || !pentry.contains( "filesystem" ) || !pentry.contains( "size" ) ) + if ( !pentry.contains( "name" ) || !pentry.contains( "size" ) ) { cError() << "Partition layout entry #" << config.indexOf( r ) << "lacks mandatory attributes, switching to default layout."; @@ -147,7 +147,7 @@ PartitionLayout::init( const QVariantList& config ) CalamaresUtils::getString( pentry, "type" ), CalamaresUtils::getUnsignedInteger( pentry, "attributes", 0 ), CalamaresUtils::getString( pentry, "mountPoint" ), - CalamaresUtils::getString( pentry, "filesystem" ), + CalamaresUtils::getString( pentry, "filesystem", "unformatted" ), CalamaresUtils::getSubMap( pentry, "features", ok ), CalamaresUtils::getString( pentry, "size", QStringLiteral( "0" ) ), CalamaresUtils::getString( pentry, "minSize", QStringLiteral( "0" ) ), diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index ed2719ca7..e5de69659 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -207,7 +207,7 @@ defaultFileSystemType: "ext4" # - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0) -# - filesystem: filesystem type +# - filesystem: filesystem type (optional parameter; fs not created if "unformatted" or unset) # - mountPoint: partition mount point (optional parameter; not mounted if unset) # - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB) # or From 6013ed52f8f9efb04365ea8b595d14a0fd2761c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Mon, 2 Nov 2020 08:57:58 -0500 Subject: [PATCH 41/72] [partition] Ignore unformatted filesystem --- src/modules/partition/jobs/FillGlobalStorageJob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index 8e7958e83..c9040877d 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -153,7 +153,7 @@ FillGlobalStorageJob::prettyDescription() const QString path = partitionMap.value( "device" ).toString(); QString mountPoint = partitionMap.value( "mountPoint" ).toString(); QString fsType = partitionMap.value( "fs" ).toString(); - if ( mountPoint.isEmpty() || fsType.isEmpty() ) + if ( mountPoint.isEmpty() || fsType.isEmpty() || fsType == QString( "unformatted" ) ) { continue; } From f78752303b4456a0d821680b9748648e3e940c4d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 15:40:32 +0100 Subject: [PATCH 42/72] [partition] Improve constructors for layout - initialize flags by default - the copy constructor was just doing the default thing, so make that explicit --- src/modules/partition/core/PartitionLayout.cpp | 14 -------------- src/modules/partition/core/PartitionLayout.h | 4 ++-- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 15b18da93..85ba683d0 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -95,20 +95,6 @@ PartitionLayout::PartitionEntry::PartitionEntry( const QString& label, PartUtils::findFS( fs, &partFileSystem ); } -PartitionLayout::PartitionEntry::PartitionEntry( const PartitionEntry& e ) - : partLabel( e.partLabel ) - , partUUID( e.partUUID ) - , partType( e.partType ) - , partAttributes( e.partAttributes ) - , partMountPoint( e.partMountPoint ) - , partFileSystem( e.partFileSystem ) - , partFeatures( e.partFeatures ) - , partSize( e.partSize ) - , partMinSize( e.partMinSize ) - , partMaxSize( e.partMaxSize ) -{ -} - bool PartitionLayout::addEntry( const PartitionEntry& entry ) diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 9720ab765..e54f28b63 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -34,7 +34,7 @@ public: QString partLabel; QString partUUID; QString partType; - quint64 partAttributes; + quint64 partAttributes = 0; QString partMountPoint; FileSystem::Type partFileSystem = FileSystem::Unknown; QVariantMap partFeatures; @@ -61,7 +61,7 @@ public: const QString& minSize = QString(), const QString& maxSize = QString() ); /// @brief Copy PartitionEntry - PartitionEntry( const PartitionEntry& e ); + PartitionEntry( const PartitionEntry& e ) = default; bool isValid() const { From 23eabd74c6b83b0663afb2743b779732690d1baf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 16:01:10 +0100 Subject: [PATCH 43/72] [partition] Set FS type explicitly if no layout is given - the "simple" constructor for PartitionEntry left the FS type set as the constructor left it -- which is Unknown by default. This leads to install failures in systems that don't set a special layout but just want a single / -- because the FS is set to Unknown. - massage the constructor and consumer of the code, push Ext4 FS in the tests and use the configured default in production. --- src/modules/partition/core/PartitionLayout.cpp | 7 ++++--- src/modules/partition/core/PartitionLayout.h | 9 +++++++-- src/modules/partition/tests/CreateLayoutsTests.cpp | 12 ++++++------ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 85ba683d0..b71512685 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -63,8 +63,9 @@ PartitionLayout::PartitionEntry::PartitionEntry() { } -PartitionLayout::PartitionEntry::PartitionEntry( const QString& mountPoint, const QString& size, const QString& minSize, const QString& maxSize ) - : partAttributes( 0 ) +PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type type, const QString& mountPoint, const QString& size, const QString& minSize, const QString& maxSize ) + : partType( type ) + , partAttributes( 0 ) , partMountPoint( mountPoint ) , partSize( size ) , partMinSize( minSize ) @@ -148,7 +149,7 @@ PartitionLayout::init( const QVariantList& config ) if ( !m_partLayout.count() ) { - addEntry( { QString( "/" ), QString( "100%" ) } ); + addEntry( { m_defaultFsType, QString( "/" ), QString( "100%" ) } ); } } diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index e54f28b63..8c02a8a41 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -44,8 +44,13 @@ public: /// @brief All-zeroes PartitionEntry PartitionEntry(); - /// @brief Parse @p mountPoint, @p size, @p minSize and @p maxSize to their respective member variables - PartitionEntry( const QString& mountPoint, + /** @brief Parse @p mountPoint, @p size, @p minSize and @p maxSize to their respective member variables + * + * Sets a specific FS type (not parsed from string like the other + * constructor). + */ + PartitionEntry( FileSystem::Type type, + const QString& mountPoint, const QString& size, const QString& minSize = QString(), const QString& maxSize = QString() ); diff --git a/src/modules/partition/tests/CreateLayoutsTests.cpp b/src/modules/partition/tests/CreateLayoutsTests.cpp index 4b76bb83a..04a06b2b3 100644 --- a/src/modules/partition/tests/CreateLayoutsTests.cpp +++ b/src/modules/partition/tests/CreateLayoutsTests.cpp @@ -59,7 +59,7 @@ CreateLayoutsTests::testFixedSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( { QString( "/" ), QString( "5MiB" ) } ) ) + if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "5MiB" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } @@ -79,7 +79,7 @@ CreateLayoutsTests::testPercentSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( { QString( "/" ), QString( "50%" ) } ) ) + if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } @@ -99,17 +99,17 @@ CreateLayoutsTests::testMixedSizePartition() PartitionRole role( PartitionRole::Role::Any ); QList< Partition* > partitions; - if ( !layout.addEntry( { QString( "/" ), QString( "5MiB" ) } ) ) + if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "5MiB" ) } ) ) { QFAIL( qPrintable( "Unable to create / partition" ) ); } - if ( !layout.addEntry( { QString( "/home" ), QString( "50%" ) } ) ) + if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/home" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create /home partition" ) ); } - if ( !layout.addEntry( { QString( "/bkup" ), QString( "50%" ) } ) ) + if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/bkup" ), QString( "50%" ) } ) ) { QFAIL( qPrintable( "Unable to create /bkup partition" ) ); } @@ -124,7 +124,7 @@ CreateLayoutsTests::testMixedSizePartition() } #ifdef WITH_KPMCORE4API -// TODO: Get a clean way to instanciate a test Device from KPMCore +// TODO: Get a clean way to instantiate a test Device from KPMCore class DevicePrivate { public: From 42014a82018d7c70bc209333f26c3f6fb1855222 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 16:21:12 +0100 Subject: [PATCH 44/72] Docs: typo (thanks jdfthetech) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a2cb426b7..d3db39089 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ git clone https://github.com/calamares/calamares.git ``` Calamares is a KDE-Frameworks and Qt-based, C++17, CMake-built application. -The dependencies are explainged in [CONTRIBUTING.md](CONTRIBUTING.md). +The dependencies are explained in [CONTRIBUTING.md](CONTRIBUTING.md). ## Contributing to Calamares From 73b5a0898d0102abd469104fbcdab56ce8d7c8fc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 21:35:43 +0100 Subject: [PATCH 45/72] [partition] Migrate the defaultFS type - remove the m_defaultFSType from PartitionLayout, because it is set on construction -- which is too early, before the configuration has been read. - make the default FS explicit in the init() calls which pass in a configuration; this needs support in the intermediate PartitionCoreModule. --- .../partition/core/PartitionCoreModule.cpp | 7 ++- .../partition/core/PartitionCoreModule.h | 6 +- .../partition/core/PartitionLayout.cpp | 59 ++++++++----------- src/modules/partition/core/PartitionLayout.h | 9 ++- .../partition/gui/PartitionViewStep.cpp | 3 +- 5 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 706f99017..14ce48b88 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -861,9 +861,9 @@ PartitionCoreModule::setBootLoaderInstallPath( const QString& path ) } void -PartitionCoreModule::initLayout( const QVariantList& config ) +PartitionCoreModule::initLayout( FileSystem::Type defaultFsType, const QVariantList& config ) { - m_partLayout.init( config ); + m_partLayout.init( defaultFsType, config ); } void @@ -875,7 +875,8 @@ PartitionCoreModule::layoutApply( Device* dev, const PartitionRole& role ) { bool isEfi = PartUtils::isEfiSystem(); - QList< Partition* > partList = m_partLayout.createPartitions( dev, firstSector, lastSector, luksPassphrase, parent, role ); + QList< Partition* > partList + = m_partLayout.createPartitions( dev, firstSector, lastSector, luksPassphrase, parent, role ); // Partition::mountPoint() tells us where it is mounted **now**, while // PartitionInfo::mountPoint() says where it will be mounted in the target system. diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 46feb5f94..46604b97c 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -156,7 +156,11 @@ public: /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); - void initLayout( const QVariantList& config = QVariantList() ); + /** @brief Initialize the default layout that will be applied + * + * See PartitionLayout::init() + */ + void initLayout( FileSystem::Type defaultFsType, const QVariantList& config = QVariantList() ); void layoutApply( Device* dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); void layoutApply( Device* dev, diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index b71512685..6c5b69b98 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -27,32 +27,10 @@ #include #include -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::PartitionLayout( const PartitionLayout& layout ) - : m_defaultFsType( layout.m_defaultFsType ) - , m_partLayout( layout.m_partLayout ) + : m_partLayout( layout.m_partLayout ) { } @@ -63,7 +41,11 @@ PartitionLayout::PartitionEntry::PartitionEntry() { } -PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type type, const QString& mountPoint, const QString& size, const QString& minSize, const QString& maxSize ) +PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type type, + const QString& mountPoint, + const QString& size, + const QString& minSize, + const QString& maxSize ) : partType( type ) , partAttributes( 0 ) , partMountPoint( mountPoint ) @@ -111,7 +93,7 @@ PartitionLayout::addEntry( const PartitionEntry& entry ) } void -PartitionLayout::init( const QVariantList& config ) +PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& config ) { bool ok; @@ -149,7 +131,7 @@ PartitionLayout::init( const QVariantList& config ) if ( !m_partLayout.count() ) { - addEntry( { m_defaultFsType, QString( "/" ), QString( "100%" ) } ); + addEntry( { defaultFsType, QString( "/" ), QString( "100%" ) } ); } } @@ -215,8 +197,8 @@ PartitionLayout::createPartitions( Device* dev, { if ( entry.partSize.unit() == CalamaresUtils::Partition::SizeUnit::Percent ) { - qint64 sectors = entry.partSize.toSectors( availableSectors + partSectorsMap.value( &entry ), - dev->logicalSize() ); + qint64 sectors + = entry.partSize.toSectors( availableSectors + partSectorsMap.value( &entry ), dev->logicalSize() ); if ( entry.partMinSize.isValid() ) { sectors = std::max( sectors, entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ) ); @@ -245,13 +227,24 @@ PartitionLayout::createPartitions( Device* dev, Partition* part = nullptr; if ( luksPassphrase.isEmpty() ) { - part = KPMHelpers::createNewPartition( - parent, *dev, role, entry.partFileSystem, currentSector, currentSector + sectors - 1, KPM_PARTITION_FLAG( None ) ); + part = KPMHelpers::createNewPartition( parent, + *dev, + role, + entry.partFileSystem, + currentSector, + currentSector + sectors - 1, + KPM_PARTITION_FLAG( None ) ); } else { - part = KPMHelpers::createNewEncryptedPartition( - parent, *dev, role, entry.partFileSystem, currentSector, currentSector + sectors - 1, luksPassphrase, KPM_PARTITION_FLAG( None ) ); + part = KPMHelpers::createNewEncryptedPartition( parent, + *dev, + role, + entry.partFileSystem, + currentSector, + currentSector + sectors - 1, + luksPassphrase, + KPM_PARTITION_FLAG( None ) ); } PartitionInfo::setFormat( part, true ); PartitionInfo::setMountPoint( part, entry.partMountPoint ); diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 8c02a8a41..24858aef8 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -83,7 +83,13 @@ public: PartitionLayout( const PartitionLayout& layout ); ~PartitionLayout(); - void init( const QVariantList& config ); + /** @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, then a single + * partition is created with the given @p defaultFsType + */ + void init( FileSystem::Type defaultFsType, const QVariantList& config ); bool addEntry( const PartitionEntry& entry ); /** @@ -98,7 +104,6 @@ public: const PartitionRole& role ); private: - FileSystem::Type m_defaultFsType; QList< PartitionEntry > m_partLayout; }; diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 13f5e77cc..561fdaba7 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -602,7 +602,8 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); m_future->setFuture( future ); - m_core->initLayout( configurationMap.value( "partitionLayout" ).toList() ); + m_core->initLayout( fsType == FileSystem::Unknown ? FileSystem::Ext4 : fsType, + configurationMap.value( "partitionLayout" ).toList() ); } From ffce79e30ea44f10e9a876c73c2f715a394511b5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Nov 2020 22:32:44 +0100 Subject: [PATCH 46/72] [partition] Initialize the filesystem type, not the partition type - Passing FileSystem::Type to the QString constructor for partition type is not what I intended. --- src/modules/partition/core/PartitionLayout.cpp | 6 +++--- src/modules/partition/core/PartitionLayout.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 6c5b69b98..b460d8bb4 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -41,14 +41,14 @@ PartitionLayout::PartitionEntry::PartitionEntry() { } -PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type type, +PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type fs, const QString& mountPoint, const QString& size, const QString& minSize, const QString& maxSize ) - : partType( type ) - , partAttributes( 0 ) + : partAttributes( 0 ) , partMountPoint( mountPoint ) + , partFileSystem( fs ) , partSize( size ) , partMinSize( minSize ) , partMaxSize( maxSize ) diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 24858aef8..6e0c73f8f 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -49,7 +49,7 @@ public: * Sets a specific FS type (not parsed from string like the other * constructor). */ - PartitionEntry( FileSystem::Type type, + PartitionEntry( FileSystem::Type fs, const QString& mountPoint, const QString& size, const QString& minSize = QString(), From 8ab5b562adc83370736cceb7c94722e564056ff4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 11:16:45 +0100 Subject: [PATCH 47/72] i18n: timezone translations for Vietnamese --- lang/tz_vi.ts | 2617 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2617 insertions(+) create mode 100644 lang/tz_vi.ts diff --git a/lang/tz_vi.ts b/lang/tz_vi.ts new file mode 100644 index 000000000..b7149efa9 --- /dev/null +++ b/lang/tz_vi.ts @@ -0,0 +1,2617 @@ + + + + + QObject + + + Africa + tz_regions + Châu phi + + + + America + tz_regions + Châu Mỹ + + + + Antarctica + tz_regions + Nam Cực + + + + Arctic + tz_regions + Bắc cực + + + + Asia + tz_regions + Châu Á + + + + Atlantic + tz_regions + Đại Tây Dương + + + + Australia + tz_regions + Châu Úc + + + + Europe + tz_regions + Châu Âu + + + + Indian + tz_regions + Ấn Độ + + + + Pacific + tz_regions + Thái Bình Dương + + + + Abidjan + tz_names + Abidjan + + + + Accra + tz_names + Accra + + + + Adak + tz_names + Adak + + + + Addis Ababa + tz_names + A-đi A-ba-ba + + + + Adelaide + tz_names + Adelaide + + + + Aden + tz_names + Aden + + + + Algiers + tz_names + Algiers + + + + Almaty + tz_names + Almaty + + + + Amman + tz_names + Amman + + + + Amsterdam + tz_names + Am-xtéc-đam + + + + Anadyr + tz_names + Anadyr + + + + Anchorage + tz_names + Anchorage + + + + Andorra + tz_names + Andorra + + + + Anguilla + tz_names + An-gui-la + + + + Antananarivo + tz_names + An-ta-na-na-ri-vô + + + + Antigua + tz_names + Antigua + + + + Apia + tz_names + A-pi-a + + + + Aqtau + tz_names + Aqtau + + + + Aqtobe + tz_names + Aqtobe + + + + Araguaina + tz_names + Araguaina + + + + Argentina/Buenos Aires + tz_names + Ác-hen-ti-na/Buenos Aires + + + + Argentina/Catamarca + tz_names + Ác-hen-ti-na/Catamarca + + + + Argentina/Cordoba + tz_names + Ác-hen-ti-na/Cordoba + + + + Argentina/Jujuy + tz_names + Ác-hen-ti-na/Jujuy + + + + Argentina/La Rioja + tz_names + Ác-hen-ti-na/La Rioja + + + + Argentina/Mendoza + tz_names + Ác-hen-ti-na/Mendoza + + + + Argentina/Rio Gallegos + tz_names + Ác-hen-ti-na/Rio Gallegos + + + + Argentina/Salta + tz_names + Ác-hen-ti-na/Salta + + + + Argentina/San Juan + tz_names + Ác-hen-ti-na/San Juan + + + + Argentina/San Luis + tz_names + Ác-hen-ti-na/San Luis + + + + Argentina/Tucuman + tz_names + Ác-hen-ti-na/Tucuman + + + + Argentina/Ushuaia + tz_names + Ác-hen-ti-na/Ushuaia + + + + Aruba + tz_names + A-ru-ba + + + + Ashgabat + tz_names + A-sơ-kha0bast + + + + Asmara + tz_names + Át-ma-ra + + + + Astrakhan + tz_names + Astrakhan + + + + Asuncion + tz_names + A-sun-sân + + + + Athens + tz_names + A-ten + + + + Atikokan + tz_names + Atikokan + + + + Atyrau + tz_names + Atyrau + + + + Auckland + tz_names + Auckland + + + + Azores + tz_names + Azores + + + + Baghdad + tz_names + Bát-đa + + + + Bahia + tz_names + Bahia + + + + Bahia Banderas + tz_names + Bahia Banderas + + + + Bahrain + tz_names + Ba-ranh + + + + Baku + tz_names + Ba-cu + + + + Bamako + tz_names + Bamako + + + + Bangkok + tz_names + Băng Cốc + + + + Bangui + tz_names + Ban-gui + + + + Banjul + tz_names + Ban-giun + + + + Barbados + tz_names + Bác-ba-đốt + + + + Barnaul + tz_names + Barnaul + + + + Beirut + tz_names + Bê-rút + + + + Belem + tz_names + Belem + + + + Belgrade + tz_names + Bê-ô-grát + + + + Belize + tz_names + Bê-li-xê + + + + Berlin + tz_names + Béc Lin + + + + Bermuda + tz_names + Béc-mu-đa + + + + Bishkek + tz_names + Bi-skec + + + + Bissau + tz_names + Bit-xao + + + + Blanc-Sablon + tz_names + Blanc-Sablon + + + + Blantyre + tz_names + Blantyre + + + + Boa Vista + tz_names + Boa Vista + + + + Bogota + tz_names + Bô-gô-ta + + + + Boise + tz_names + Boise + + + + Bougainville + tz_names + Bougainville + + + + Bratislava + tz_names + Bra-tít-xla-va + + + + Brazzaville + tz_names + Brazzaville + + + + Brisbane + tz_names + Brisbane + + + + Broken Hill + tz_names + Đồi Broken + + + + Brunei + tz_names + Bru-nây + + + + Brussels + tz_names + Brúc-xen + + + + Bucharest + tz_names + Bu-ca-rét + + + + Budapest + tz_names + Bu-đa-pét + + + + Bujumbura + tz_names + Bu-gium-bu-ra + + + + Busingen + tz_names + Busingen + + + + Cairo + tz_names + Cai Rô + + + + Cambridge Bay + tz_names + Vịnh Cambridge + + + + Campo Grande + tz_names + Campo Grande + + + + Canary + tz_names + Canary + + + + Cancun + tz_names + Cancun + + + + Cape Verde + tz_names + Cáp-ve + + + + Caracas + tz_names + Ca-ra-cát + + + + Casablanca + tz_names + Casablanca + + + + Casey + tz_names + Casey + + + + Cayenne + tz_names + Cayenne + + + + Cayman + tz_names + Quần đảo Cay-man + + + + Ceuta + tz_names + Ceuta + + + + Chagos + tz_names + Chagos + + + + Chatham + tz_names + Chatham + + + + Chicago + tz_names + Chi Ca Gô + + + + Chihuahua + tz_names + Chihuahua + + + + Chisinau + tz_names + Ki-si-nhốp + + + + Chita + tz_names + Chita + + + + Choibalsan + tz_names + Choibalsan + + + + Christmas + tz_names + Christmas + + + + Chuuk + tz_names + Chuuk + + + + Cocos + tz_names + Cocos + + + + Colombo + tz_names + Cô Lôm Bô + + + + Comoro + tz_names + (Liên bang) Cô-mo + + + + Conakry + tz_names + Cô-na-cri + + + + Copenhagen + tz_names + Cô-pen-ha-gen + + + + Costa Rica + tz_names + Cốt-xta-ri-ca + + + + Creston + tz_names + Creston + + + + Cuiaba + tz_names + Cuiaba + + + + Curacao + tz_names + Cu-ra-xao + + + + Currie + tz_names + Currie + + + + Dakar + tz_names + Dakar + + + + Damascus + tz_names + Đa-mát + + + + Danmarkshavn + tz_names + Danmarkshavn + + + + Dar es Salaam + tz_names + Dar es Salaam + + + + Darwin + tz_names + Darwin + + + + Davis + tz_names + Davis + + + + Dawson + tz_names + Dawson + + + + Dawson Creek + tz_names + Dawson Creek + + + + Denver + tz_names + Denver + + + + Detroit + tz_names + Detroit + + + + Dhaka + tz_names + Đắc-ca + + + + Dili + tz_names + Đi-li + + + + Djibouti + tz_names + Cộng hòa Gi-bu-ti + + + + Dominica + tz_names + Đô-mi-ni-ca-na + + + + Douala + tz_names + Douala + + + + Dubai + tz_names + Đu Bai + + + + Dublin + tz_names + Đu-blin + + + + DumontDUrville + tz_names + DumontDUrville + + + + Dushanbe + tz_names + Đu-san-be + + + + Easter + tz_names + Đảo Phục Sinh + + + + Edmonton + tz_names + Edmonton + + + + Efate + tz_names + Efate + + + + Eirunepe + tz_names + Eirunepe + + + + El Aaiun + tz_names + El Aaiun + + + + El Salvador + tz_names + En Xan-va-đo + + + + Enderbury + tz_names + Đảo Enderbury + + + + Eucla + tz_names + Eucla + + + + Fakaofo + tz_names + Fakaofo + + + + Famagusta + tz_names + Famagusta + + + + Faroe + tz_names + Quần đảo Fa-rô + + + + Fiji + tz_names + Phi-gi + + + + Fort Nelson + tz_names + Fort Nelson + + + + Fortaleza + tz_names + Fortaleza + + + + Freetown + tz_names + Phritao + + + + Funafuti + tz_names + Funafuti + + + + Gaborone + tz_names + Ga-bô-rô-nê + + + + Galapagos + tz_names + Quần đảo Galapagos + + + + Gambier + tz_names + Gambier + + + + Gaza + tz_names + Dải Gaza + + + + Gibraltar + tz_names + Gibraltar + + + + Glace Bay + tz_names + Vịnh Glace + + + + Godthab + tz_names + Nu-úc + + + + Goose Bay + tz_names + Vịnh Goose + + + + Grand Turk + tz_names + Đảo Grand Turk + + + + Grenada + tz_names + Grê-na-đa + + + + Guadalcanal + tz_names + Guadalcanal + + + + Guadeloupe + tz_names + Goa-đê-lốp + + + + Guam + tz_names + Guam + + + + Guatemala + tz_names + Goa-tê-ma-la + + + + Guayaquil + tz_names + Guayaquil + + + + Guernsey + tz_names + Guernsey + + + + Guyana + tz_names + Guy-a-na + + + + Halifax + tz_names + Halifa + + + + Harare + tz_names + Ha-ra-rê + + + + Havana + tz_names + Ha Va Na + + + + Hebron + tz_names + Hebron + + + + Helsinki + tz_names + Hen-sin-ki + + + + Hermosillo + tz_names + Hermosillo + + + + Ho Chi Minh + tz_names + Hồ Chí Minh + + + + Hobart + tz_names + Hobart + + + + Hong Kong + tz_names + Hồng Công + + + + Honolulu + tz_names + Honolulu + + + + Hovd + tz_names + Khovd + + + + Indiana/Indianapolis + tz_names + Indiana/Indianapolis + + + + Indiana/Knox + tz_names + Indiana/Knox + + + + Indiana/Marengo + tz_names + Indiana/Marengo + + + + Indiana/Petersburg + tz_names + Indiana/Petersburg + + + + Indiana/Tell City + tz_names + Indiana/Tell City + + + + Indiana/Vevay + tz_names + Indiana/Vevay + + + + Indiana/Vincennes + tz_names + Indiana/Vincennes + + + + Indiana/Winamac + tz_names + Indiana/Winamac + + + + Inuvik + tz_names + Inuvik + + + + Iqaluit + tz_names + Iqaluit + + + + Irkutsk + tz_names + Irkutsk + + + + Isle of Man + tz_names + Đảo Man + + + + Istanbul + tz_names + Istanbul + + + + Jakarta + tz_names + Gia Các Ta + + + + Jamaica + tz_names + Gia-mai-ca + + + + Jayapura + tz_names + Jayapura + + + + Jersey + tz_names + Jersey + + + + Jerusalem + tz_names + Giê-ru-xa-lem + + + + Johannesburg + tz_names + Johannesburg + + + + Juba + tz_names + Juba + + + + Juneau + tz_names + Juneau + + + + Kabul + tz_names + Ka-bun + + + + Kaliningrad + tz_names + Kaliningrad + + + + Kamchatka + tz_names + Bán đảo Kamchatka + + + + Kampala + tz_names + Campala + + + + Karachi + tz_names + Karachi + + + + Kathmandu + tz_names + Cát-man-đu + + + + Kentucky/Louisville + tz_names + Ken túc ky/Louisville + + + + Kentucky/Monticello + tz_names + Ken túc ky/Monticello + + + + Kerguelen + tz_names + Đảo Kerguelen + + + + Khandyga + tz_names + Khandyga + + + + Khartoum + tz_names + Khác-tum + + + + Kiev + tz_names + Kyiv + + + + Kigali + tz_names + Ki-ga-li + + + + Kinshasa + tz_names + Kin-xa-sa + + + + Kiritimati + tz_names + Kiritimati + + + + Kirov + tz_names + Kirov + + + + Kolkata + tz_names + Kolkata + + + + Kosrae + tz_names + Kosrae + + + + Kralendijk + tz_names + Kralendijk + + + + Krasnoyarsk + tz_names + Krasnoyarsk + + + + Kuala Lumpur + tz_names + Kuala Lam Pơ + + + + Kuching + tz_names + Kuching + + + + Kuwait + tz_names + Kuwait + + + + Kwajalein + tz_names + Kwajalein + + + + La Paz + tz_names + La Pa-xơ + + + + Lagos + tz_names + Lagos + + + + Libreville + tz_names + Li-brơ-vin + + + + Lima + tz_names + Lima + + + + Lindeman + tz_names + Hồ Lindeman + + + + Lisbon + tz_names + Lít Bon + + + + Ljubljana + tz_names + Liu-bli-an-na + + + + Lome + tz_names + Lô-mê + + + + London + tz_names + Luân Đôn + + + + Longyearbyen + tz_names + Longyearbyen + + + + Lord Howe + tz_names + Đảo Lord Howe + + + + Los Angeles + tz_names + Lốt Ăng Giơ Lét + + + + Lower Princes + tz_names + Lower Princes + + + + Luanda + tz_names + Lu-an-đa + + + + Lubumbashi + tz_names + Lubumbashi + + + + Lusaka + tz_names + Lu-xa-ca + + + + Luxembourg + tz_names + Lúc-xăm-bua + + + + Macau + tz_names + Ma Cao + + + + Maceio + tz_names + Maceio + + + + Macquarie + tz_names + Macquarie + + + + Madeira + tz_names + Madeira + + + + Madrid + tz_names + Ma Rích + + + + Magadan + tz_names + Magadan + + + + Mahe + tz_names + Mahe + + + + Majuro + tz_names + Majuro + + + + Makassar + tz_names + Makassar + + + + Malabo + tz_names + Malabo + + + + Maldives + tz_names + Man-đi-vơ + + + + Malta + tz_names + Man-Man-tata + + + + Managua + tz_names + Ma-na-goa + + + + Manaus + tz_names + Manaus + + + + Manila + tz_names + Manila + + + + Maputo + tz_names + Maputo + + + + Mariehamn + tz_names + Mariehamn + + + + Marigot + tz_names + Marigot + + + + Marquesas + tz_names + Quần đảo Marquesas + + + + Martinique + tz_names + Martinique + + + + Maseru + tz_names + Ma-xê-ru + + + + Matamoros + tz_names + Matamoros + + + + Mauritius + tz_names + Mô-ri-xơ + + + + Mawson + tz_names + Mawson + + + + Mayotte + tz_names + Mayotte + + + + Mazatlan + tz_names + Mazatlan + + + + Mbabane + tz_names + Mbabane + + + + McMurdo + tz_names + McMurdo + + + + Melbourne + tz_names + Melbourne + + + + Menominee + tz_names + Menominee + + + + Merida + tz_names + Merida + + + + Metlakatla + tz_names + Metlakatla + + + + Mexico City + tz_names + Thành phố Mê Xi Cô + + + + Midway + tz_names + Midway + + + + Minsk + tz_names + Min-xcơ + + + + Miquelon + tz_names + Mi-kê-lân + + + + Mogadishu + tz_names + Mô-ga-đi-su + + + + Monaco + tz_names + Mô-na-cô + + + + Moncton + tz_names + Moncton + + + + Monrovia + tz_names + Monrovia + + + + Monterrey + tz_names + Monterrey + + + + Montevideo + tz_names + Mông-tơ-vi-di-ô + + + + Montserrat + tz_names + Montserrat + + + + Moscow + tz_names + Mát Cơ Va + + + + Muscat + tz_names + Mu Cát + + + + Nairobi + tz_names + Nai-rô-bi + + + + Nassau + tz_names + Nát-xô + + + + Nauru + tz_names + Na-u-ru + + + + Ndjamena + tz_names + Gia-mê-na + + + + New York + tz_names + Nữu Ước + + + + Niamey + tz_names + Ni-a-mây + + + + Nicosia + tz_names + Ni-cô-xi-a + + + + Nipigon + tz_names + Nipigon + + + + Niue + tz_names + Ni-u-ê + + + + Nome + tz_names + Nome + + + + Norfolk + tz_names + Norfolk + + + + Noronha + tz_names + Noronha + + + + North Dakota/Beulah + tz_names + Bắc Dakota/Beulah + + + + North Dakota/Center + tz_names + Bắc Dakota/Center + + + + North Dakota/New Salem + tz_names + Bắc Dakota/New Salem + + + + Nouakchott + tz_names + Nu-ác-sốt + + + + Noumea + tz_names + No-mi + + + + Novokuznetsk + tz_names + Novokuznetsk + + + + Novosibirsk + tz_names + Novosibirsk + + + + Ojinaga + tz_names + Ojinaga + + + + Omsk + tz_names + Omsk + + + + Oral + tz_names + Oral + + + + Oslo + tz_names + Ốt-xlô + + + + Ouagadougou + tz_names + U-a-ga-đu-gu + + + + Pago Pago + tz_names + Pago Pago + + + + Palau + tz_names + Pa-lau + + + + Palmer + tz_names + Palmer + + + + Panama + tz_names + Pa-na-ma + + + + Pangnirtung + tz_names + Pangnirtung + + + + Paramaribo + tz_names + Pa-ra-ma-ri-bô + + + + Paris + tz_names + Pa Ri + + + + Perth + tz_names + Perth + + + + Phnom Penh + tz_names + Phnôm Pênh + + + + Phoenix + tz_names + Phoenix + + + + Pitcairn + tz_names + Quần đảo Pít-cơn + + + + Podgorica + tz_names + Pốt-gô-ri-xa + + + + Pohnpei + tz_names + Pohnpei + + + + Pontianak + tz_names + Pontianak + + + + Port Moresby + tz_names + Cảng Moresby + + + + Port of Spain + tz_names + Cảng Tây Ban Nha + + + + Port-au-Prince + tz_names + Cảng au Prince + + + + Porto Velho + tz_names + Cảng Velho + + + + Porto-Novo + tz_names + Cảng-Novo + + + + Prague + tz_names + Praha + + + + Puerto Rico + tz_names + Cảng Rico + + + + Punta Arenas + tz_names + Đấu trường Punta + + + + Pyongyang + tz_names + Bình Nhưỡng + + + + Qatar + tz_names + Ca-ta + + + + Qostanay + tz_names + Kostanay + + + + Qyzylorda + tz_names + Kyzylorda + + + + Rainy River + tz_names + Rainy River + + + + Rankin Inlet + tz_names + Rankin Inlet + + + + Rarotonga + tz_names + Rarotonga + + + + Recife + tz_names + Recife + + + + Regina + tz_names + Regina + + + + Resolute + tz_names + Resolute + + + + Reunion + tz_names + Rê-u-niên + + + + Reykjavik + tz_names + Rây-ki-a-vích + + + + Riga + tz_names + Ri-ga + + + + Rio Branco + tz_names + Rio Branco + + + + Riyadh + tz_names + Ri-át + + + + Rome + tz_names + Rô Ma + + + + Rothera + tz_names + Rothera + + + + Saipan + tz_names + Saipan + + + + Sakhalin + tz_names + Sakhalin + + + + Samara + tz_names + Samara + + + + Samarkand + tz_names + Samarkand + + + + San Marino + tz_names + San Marino + + + + Santarem + tz_names + Santarem + + + + Santiago + tz_names + Santiago + + + + Santo Domingo + tz_names + Xan-tô Đô-min-gô + + + + Sao Paulo + tz_names + Sao Paolo + + + + Sao Tome + tz_names + Sao Tô-mê + + + + Sarajevo + tz_names + Xa-ra-ê-vô + + + + Saratov + tz_names + Saratov + + + + Scoresbysund + tz_names + Scoresby Sund + + + + Seoul + tz_names + Xê un + + + + Shanghai + tz_names + Thượng Hải + + + + Simferopol + tz_names + Simferopol + + + + Singapore + tz_names + Singapo + + + + Sitka + tz_names + Sitka + + + + Skopje + tz_names + Xcốp-pi-ê + + + + Sofia + tz_names + Sofia + + + + South Georgia + tz_names + Nam Georgia + + + + Srednekolymsk + tz_names + Srednekolymsk + + + + St Barthelemy + tz_names + St Barthelemy + + + + St Helena + tz_names + St Helena + + + + St Johns + tz_names + St Johns + + + + St Kitts + tz_names + St Kitts + + + + St Lucia + tz_names + St Lucia + + + + St Thomas + tz_names + St Thomas + + + + St Vincent + tz_names + St Vincent + + + + Stanley + tz_names + Stanley + + + + Stockholm + tz_names + Xtốc-khôm + + + + Swift Current + tz_names + Swift Current + + + + Sydney + tz_names + Xít ni + + + + Syowa + tz_names + Syowa + + + + Tahiti + tz_names + Tahiti + + + + Taipei + tz_names + Đài Bắc + + + + Tallinn + tz_names + Ta-lin + + + + Tarawa + tz_names + Tarawa + + + + Tashkent + tz_names + Ta-sơ-ken + + + + Tbilisi + tz_names + Tbi-li-xi + + + + Tegucigalpa + tz_names + Te-gu-xi-gan-pa + + + + Tehran + tz_names + Tê-hê-ran + + + + Thimphu + tz_names + Thim-bu + + + + Thule + tz_names + Thule + + + + Thunder Bay + tz_names + Vịnh Thunder + + + + Tijuana + tz_names + Tijuana + + + + Tirane + tz_names + Ti-ra-na + + + + Tokyo + tz_names + Tô Ky Ôs + + + + Tomsk + tz_names + Tomsk + + + + Tongatapu + tz_names + Tongatapu + + + + Toronto + tz_names + Tô Rôn Tô + + + + Tortola + tz_names + Tortola + + + + Tripoli + tz_names + Tri Pô Li + + + + Troll + tz_names + Troll + + + + Tunis + tz_names + Tuy-nít + + + + Ulaanbaatar + tz_names + Ulan Bato + + + + Ulyanovsk + tz_names + Ulyanovsk + + + + Urumqi + tz_names + Urumqi + + + + Ust-Nera + tz_names + Ust-Nera + + + + Uzhgorod + tz_names + Uzhgorod + + + + Vaduz + tz_names + Vaduz + + + + Vancouver + tz_names + Van Cô Vơ + + + + Vatican + tz_names + Va Ti Can + + + + Vienna + tz_names + Viên + + + + Vientiane + tz_names + Viêng Chăn + + + + Vilnius + tz_names + Vin-ni-út + + + + Vladivostok + tz_names + Vladivostok + + + + Volgograd + tz_names + Volgograd + + + + Vostok + tz_names + Vostok + + + + Wake + tz_names + Wake + + + + Wallis + tz_names + Wa Li + + + + Warsaw + tz_names + Vác-sa-va + + + + Whitehorse + tz_names + Whitehorse + + + + Windhoek + tz_names + Windhoek + + + + Winnipeg + tz_names + Winnipeg + + + + Yakutat + tz_names + Yakutat + + + + Yakutsk + tz_names + Yakutsk + + + + Yangon + tz_names + Ragoon + + + + Yekaterinburg + tz_names + Yekaterinburg + + + + Yellowknife + tz_names + Yellowknife + + + + Yerevan + tz_names + Ê-rê-van + + + + Zagreb + tz_names + Da-gờ-rép + + + + Zaporozhye + tz_names + Zaporizhia + + + + Zurich + tz_names + Zurich + + + From ed95c4a5413a76c6e1086d33a4bc45755b910e0b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 11:52:23 +0100 Subject: [PATCH 48/72] CMake: pre-release housekeeping --- CHANGES | 7 ++++++- CMakeLists.txt | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 85accf44d..27abd9eef 100644 --- a/CHANGES +++ b/CHANGES @@ -7,7 +7,7 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. -# 3.2.33 (unreleased) # +# 3.2.33 (2020-11-03) # This release contains contributions from (alphabetically by first name): - Anke Boersma @@ -28,6 +28,11 @@ This release contains contributions from (alphabetically by first name): and usernames). (Thanks Artem) - Various cleanups and documentation improvements in the *partition* module, and configurable GPT name for swap. (Thanks Gaël) + - The *users* module now has a more detailed way to specify + user groups -- which may be system groups rather than user-GIDs. + A new option in each group can require that the group already + exists in the target system, allowing for better consistency checks + with the squashfs. # 3.2.32.1 (2020-10-17) # diff --git a/CMakeLists.txt b/CMakeLists.txt index b20ce50d9..d8744afb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ project( CALAMARES VERSION 3.2.33 LANGUAGES C CXX ) -set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development +set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development ### OPTIONS # From 7c268b2e4d5458ba5705fecd9d6395823cd92606 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 12:48:12 +0100 Subject: [PATCH 49/72] [users] Correct terminology in configuration documentation --- src/modules/users/users.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf index ee1ccbf1c..8606fd224 100644 --- a/src/modules/users/users.conf +++ b/src/modules/users/users.conf @@ -3,16 +3,16 @@ # # Configuration for the one-user-system user module. # -# Besides these settings, the user module also places the following -# keys into the globalconfig area, based on user input in the view step. +# Besides these settings, the users module also places the following +# keys into the Global Storage area, based on user input in the view step. # # - hostname # - username # - password (obscured) # - autologinUser (if enabled, set to username) # -# These globalconfig keys are set when the jobs for this module -# are created. +# These Global Storage keys are set when the configuration for this module +# is read and when they are modified in the UI. --- # Used as default groups for the created user. # Adjust to your Distribution defaults. From 36f9fd56a3e6263b726a4b4d013aadfbb6a66400 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 12:54:19 +0100 Subject: [PATCH 50/72] [users] Expand the example config with new possibilities --- src/modules/users/users.conf | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf index 8606fd224..2e09ae123 100644 --- a/src/modules/users/users.conf +++ b/src/modules/users/users.conf @@ -16,13 +16,29 @@ --- # Used as default groups for the created user. # Adjust to your Distribution defaults. +# +# Each entry in the *defaultGroups* list is either: +# - a string, naming a group; this is a **non**-system group +# which does not need to exist in the target system; if it +# does not exist, it will be created. +# - an entry with subkeys *name*, *must_exist* and *system*; +# if the group *must_exist* and does not, an error is thrown +# and the installation fails. +# +# The group is created if it does not exist, and it is +# created as a system group (GID < 1000) or user group +# (GID >= 1000) depending on the value of *system*. defaultGroups: - - users + - name: users + must_exist: true + system: true - lp - video - network - storage - - wheel + - name: wheel + must_exist: false + system: true - audio # Some Distributions require a 'autologin' group for the user. From 3bf57c7785a5efd6c43d50b97212c6a995598953 Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 3 Nov 2020 13:55:24 +0200 Subject: [PATCH 51/72] Use graphical decryption prompt with plymouth as adviced here: https://wiki.archlinux.org/index.php/plymouth#The_plymouth_hook --- src/modules/initcpiocfg/main.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index aef980e25..6e86b3908 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -123,10 +123,6 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): openswap_hook = False unencrypted_separate_boot = False - # It is important that the plymouth hook comes before any encrypt hook - if detect_plymouth(): - hooks.append("plymouth") - for partition in partitions: if partition["fs"] == "linuxswap" and not partition.get("claimed", None): # Skip foreign swap @@ -154,7 +150,10 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): hooks.append("usr") if encrypt_hook: - hooks.append("encrypt") + if detect_plymouth(): + hooks.append("plymouth-encrypt") + else: + hooks.append("encrypt") if not unencrypted_separate_boot and \ os.path.isfile( os.path.join(root_mount_point, "crypto_keyfile.bin") From 84558333bfe1e94e40a7964cf4a7ac50a2112f4e Mon Sep 17 00:00:00 2001 From: Chrysostomus Date: Tue, 3 Nov 2020 13:57:19 +0200 Subject: [PATCH 52/72] Regular plymouth hook is also still needed --- src/modules/initcpiocfg/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index 6e86b3908..6e3de6931 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -123,6 +123,10 @@ def modify_mkinitcpio_conf(partitions, root_mount_point): openswap_hook = False unencrypted_separate_boot = False + # It is important that the plymouth hook comes before any encrypt hook + if detect_plymouth(): + hooks.append("plymouth") + for partition in partitions: if partition["fs"] == "linuxswap" and not partition.get("claimed", None): # Skip foreign swap From f898840e16ced0d9b5eada82118b25d7441695b2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 13:02:49 +0100 Subject: [PATCH 53/72] [users] Expand schema to cover new possibilities --- src/modules/users/users.schema.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml index 310df350f..81088032c 100644 --- a/src/modules/users/users.schema.yaml +++ b/src/modules/users/users.schema.yaml @@ -11,7 +11,16 @@ properties: # Group settings defaultGroups: type: array - items: { type: string } + items: + oneOf: + - type: string + - type: object + properties: + name: { type: string } + must_exist: { type: boolean, default: false } + system: { type: boolean, default: false } + additionalProperties: false + required: [ name ] autologinGroup: { type: string } sudoersGroup: { type: string } # Skip login (depends on displaymanager support) From b6534c3ebff1d9876eca376a3683f49700d42cea Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 15:01:13 +0100 Subject: [PATCH 54/72] Changes: credits adjustment --- CHANGES | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 27abd9eef..98db4d483 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ This release contains contributions from (alphabetically by first name): - Andrius Štikonas - Artem Grinev - Gaël PORTAY + - Matti Hyttinen - TTran Me ## Core ## @@ -23,6 +24,8 @@ This release contains contributions from (alphabetically by first name): - Vietnamese translations have been added. Welcome! (Thanks TTran) ## Modules ## + - The *initcpiocfg* module should support plymouth with encryption + now. (Thanks Matti) - The *keyboard* and *keyboardq* modules now share backend code and handle non-ASCII layouts better (for setting passwords and usernames). (Thanks Artem) @@ -32,7 +35,7 @@ This release contains contributions from (alphabetically by first name): user groups -- which may be system groups rather than user-GIDs. A new option in each group can require that the group already exists in the target system, allowing for better consistency checks - with the squashfs. + with the squashfs. #1523 # 3.2.32.1 (2020-10-17) # From c7eb8e1d2c5a7133e38c73afa967b37354252fab Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Tue, 3 Nov 2020 15:07:22 +0100 Subject: [PATCH 55/72] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_az.ts | 8 ++--- lang/calamares_az_AZ.ts | 8 ++--- lang/calamares_he.ts | 2 +- lang/calamares_hu.ts | 2 +- lang/calamares_ko.ts | 74 ++++++++++++++++++++--------------------- lang/calamares_lt.ts | 10 +++--- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/lang/calamares_az.ts b/lang/calamares_az.ts index e73b01885..cad678b40 100644 --- a/lang/calamares_az.ts +++ b/lang/calamares_az.ts @@ -619,17 +619,17 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir. This storage device already has an operating system on it, but the partition table <strong>%1</strong> is different from the needed <strong>%2</strong>.<br/> - + Bu yaddaş qurğusunda artıq əməliyyat sistemi var, lakin, bölmə cədvəli <strong>%1</strong>, lazım olan <strong>%2</strong> ilə fərqlidir.<br/> This storage device has one of its partitions <strong>mounted</strong>. - + Bu yaddaş qurğusunda bölmələrdən biri <strong>quraşdırılmışdır</strong>. This storage device is a part of an <strong>inactive RAID</strong> device. - + Bu yaddaş qurğusu <strong>qeyri-aktiv RAİD</strong> qurğusunun bir hissəsidir. @@ -2869,7 +2869,7 @@ Output: Directory not found - + Qovluq tapılmadı diff --git a/lang/calamares_az_AZ.ts b/lang/calamares_az_AZ.ts index 51ef10496..161a04990 100644 --- a/lang/calamares_az_AZ.ts +++ b/lang/calamares_az_AZ.ts @@ -619,17 +619,17 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir. This storage device already has an operating system on it, but the partition table <strong>%1</strong> is different from the needed <strong>%2</strong>.<br/> - + Bu yaddaş qurğusunda artıq əməliyyat sistemi var, lakin, bölmə cədvəli <strong>%1</strong>, lazım olan <strong>%2</strong> ilə fərqlidir.<br/> This storage device has one of its partitions <strong>mounted</strong>. - + Bu yaddaş qurğusunda bölmələrdən biri <strong>quraşdırılmışdır</strong>. This storage device is a part of an <strong>inactive RAID</strong> device. - + Bu yaddaş qurğusu <strong>qeyri-aktiv RAİD</strong> qurğusunun bir hissəsidir. @@ -2869,7 +2869,7 @@ Output: Directory not found - + Qovluq tapılmadı diff --git a/lang/calamares_he.ts b/lang/calamares_he.ts index e87f6bb19..5ed81a899 100644 --- a/lang/calamares_he.ts +++ b/lang/calamares_he.ts @@ -437,7 +437,7 @@ The installer will quit and all changes will be lost. Unknown exception type - טיפוס חריגה אינו מוכר + סוג חריגה לא מוכר diff --git a/lang/calamares_hu.ts b/lang/calamares_hu.ts index f7651406c..e0ca6cd41 100644 --- a/lang/calamares_hu.ts +++ b/lang/calamares_hu.ts @@ -1620,7 +1620,7 @@ Telepítés nem folytatható. <a href="#details">Részletek...</a> <h1>License Agreement</h1> - + <h1>Licenszszerződés</h1> diff --git a/lang/calamares_ko.ts b/lang/calamares_ko.ts index 481637f00..3a5820569 100644 --- a/lang/calamares_ko.ts +++ b/lang/calamares_ko.ts @@ -304,12 +304,12 @@ Calamares Initialization Failed - Calamares 초기화 실패 + 깔라마레스 초기화 실패 %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. - %1 가 설치될 수 없습니다. Calamares가 모든 구성된 모듈을 불러올 수 없었습니다. 이것은 Calamares가 분포에 의해 사용되는 방식에서 비롯된 문제입니다. + %1 가 설치될 수 없습니다. 깔라마레스가 모든 구성된 모듈을 불러올 수 없었습니다. 이것은 깔라마레스가 배포판에서 사용되는 방식에서 발생한 문제입니다. @@ -617,17 +617,17 @@ The installer will quit and all changes will be lost. This storage device already has an operating system on it, but the partition table <strong>%1</strong> is different from the needed <strong>%2</strong>.<br/> - + 이 스토리지 장치에는 이미 운영 체제가 설치되어 있으나 <strong>%1</strong> 파티션 테이블이 필요로 하는 <strong>%2</strong>와 다릅니다.<br/> This storage device has one of its partitions <strong>mounted</strong>. - + 이 스토리지 장치는 하나 이상의 <strong>마운트된</strong> 파티션을 갖고 있습니다. This storage device is a part of an <strong>inactive RAID</strong> device. - + 이 스토리지 장치는 <strong>비활성화된 RAID</strong> 장치의 일부입니다. @@ -730,7 +730,7 @@ The installer will quit and all changes will be lost. Set timezone to %1/%2. - + 표준시간대를 %1/%2로 설정합니다. @@ -790,22 +790,22 @@ The installer will quit and all changes will be lost. <h1>Welcome to the Calamares setup program for %1</h1> - + <h1> 깔라마레스 설치 프로그램 %1에 오신 것을 환영합니다</h1> <h1>Welcome to %1 setup</h1> - + <h1>%1 설치에 오신 것을 환영합니다</h1> <h1>Welcome to the Calamares installer for %1</h1> - + <h1>깔라마레스 인스톨러 %1에 오신 것을 환영합니다</h1> <h1>Welcome to the %1 installer</h1> - + <h1>%1 인스톨러에 오신 것을 환영합니다</h1> @@ -815,7 +815,7 @@ The installer will quit and all changes will be lost. '%1' is not allowed as username. - + '%1'은 사용자 이름으로 허용되지 않습니다. @@ -840,7 +840,7 @@ The installer will quit and all changes will be lost. '%1' is not allowed as hostname. - + '%1'은 호스트 이름으로 허용되지 않습니다. @@ -1813,7 +1813,7 @@ The installer will quit and all changes will be lost. Timezone: %1 - + 표준시간대: %1 @@ -1945,7 +1945,7 @@ The installer will quit and all changes will be lost. <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - <html><head/><body><h1>OEM 구성</h1> <p>Calamares는 대상 시스템을 구성하는 동안 OEM 설정을 사용합니다.</p></body></html> + <html><head/><body><h1>OEM 구성</h1> <p>깔라마레스는 대상 시스템을 구성하는 동안 OEM 설정을 사용합니다.</p></body></html> @@ -1973,22 +1973,22 @@ The installer will quit and all changes will be lost. Timezone: %1 - + 표준시간대: %1 Select your preferred Zone within your Region. - + 선호하는 표준시간대와 지역을 선택하세요. Zones - + 표준시간대 You can fine-tune Language and Locale settings below. - + 아래에서 언어 및 로케일을 상세하게 설정할 수 있습니다. @@ -2864,7 +2864,7 @@ Output: Directory not found - + 디렉터리를 찾을 수 없습니다 @@ -3044,7 +3044,7 @@ Output: Calamares cannot start KPMCore for the file-system resize job. - Calamares는 파일 시스템 크기 조정 작업을 위해 KPMCore를 시작할 수 없습니다. + 깔라마레스는 파일 시스템 크기 조정 작업을 위해 KPMCore를 시작할 수 없습니다. @@ -3482,18 +3482,18 @@ Output: KDE user feedback - + KDE 사용자 의견 Configuring KDE user feedback. - + KDE 사용자 의견을 설정하는 중입니다. Error in KDE user feedback configuration. - + KDE 사용자 의견 설정 중에 오류가 발생했습니다. @@ -3744,7 +3744,7 @@ Output: <h1>Welcome to the Calamares setup program for %1.</h1> - <h1>%1에 대한 Calamares 설정 프로그램에 오신 것을 환영합니다.</h1> + <h1>%1에 대한 깔라마레스 설정 프로그램에 오신 것을 환영합니다.</h1> @@ -3754,7 +3754,7 @@ Output: <h1>Welcome to the Calamares installer for %1.</h1> - <h1>%1을 위한 Calamares 설치 관리자에 오신 것을 환영합니다.</h1> + <h1>%1을 위한 깔라마레스 설치 관리자에 오신 것을 환영합니다.</h1> @@ -3877,7 +3877,7 @@ Output: Keyboard Variant - + 키보드 유형 @@ -3890,7 +3890,7 @@ Output: Change - + 변경 @@ -3941,7 +3941,7 @@ Output: Pick your user name and credentials to login and perform admin tasks - + 로그인 및 관리자 작업을 수행하려면 사용자 이름과 자격 증명을 선택하세요 @@ -3961,7 +3961,7 @@ Output: Login Name - + 로그인 이름 @@ -4006,7 +4006,7 @@ Output: Validate passwords quality - + 패스워드 품질 검증 @@ -4016,12 +4016,12 @@ Output: Log in automatically without asking for the password - + 패스워드를 묻지 않고 자동으로 로그인합니다 Reuse user password as root password - + 사용자 패스워드를 루트 패스워드로 재사용합니다 @@ -4031,22 +4031,22 @@ Output: Choose a root password to keep your account safe. - + 당신의 계정을 안전하게 보호하기 위해서 루트 패스워드를 선택하세요. Root Password - + 루트 패스워드 Repeat Root Password - + 루트 패스워드 확인 Enter the same password twice, so that it can be checked for typing errors. - + 입력 오류를 확인하기 위해서 동일한 패스워드를 두번 입력해주세요. @@ -4060,7 +4060,7 @@ Output: About - Calamares에 대하여 + 깔라마레스에 대하여 diff --git a/lang/calamares_lt.ts b/lang/calamares_lt.ts index 676603ca3..0adb509ac 100644 --- a/lang/calamares_lt.ts +++ b/lang/calamares_lt.ts @@ -2870,7 +2870,7 @@ Išvestis: Directory not found - + Katalogas nerastas @@ -3885,7 +3885,7 @@ Išvestis: Keyboard Variant - + Klaviatūros variantas @@ -3989,7 +3989,7 @@ Išvestis: Login Name - + Prisijungimo vardas @@ -4009,7 +4009,7 @@ Išvestis: This name will be used if you make the computer visible to others on a network. - + Šis vardas bus naudojamas, jeigu padarysite savo kompiuterį matomą kitiems naudotojams tinkle. @@ -4074,7 +4074,7 @@ Išvestis: Enter the same password twice, so that it can be checked for typing errors. - + Norint įsitikinti, kad rašydami slaptažodį nesuklydote, įrašykite tą patį slaptažodį du kartus. From 1ce126c01ee6d36b2f765362c2c50faf9eb43ff9 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Tue, 3 Nov 2020 15:07:22 +0100 Subject: [PATCH 56/72] i18n: [python] Automatic merge of Transifex translations --- lang/python/az/LC_MESSAGES/python.po | 2 ++ lang/python/az_AZ/LC_MESSAGES/python.po | 6 ++++-- lang/python/ko/LC_MESSAGES/python.po | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lang/python/az/LC_MESSAGES/python.po b/lang/python/az/LC_MESSAGES/python.po index 516429c2d..8637bfe7e 100644 --- a/lang/python/az/LC_MESSAGES/python.po +++ b/lang/python/az/LC_MESSAGES/python.po @@ -206,6 +206,8 @@ msgid "" "The displaymanagers list is empty or undefined in both globalstorage and " "displaymanager.conf." msgstr "" +"Ekran menecerləri siyahısı həm qlobal yaddaşda, həm də displaymanager.conf-" +"da boşdur və ya təyin olunmamışdır." #: src/modules/displaymanager/main.py:977 msgid "Display manager configuration was incomplete" diff --git a/lang/python/az_AZ/LC_MESSAGES/python.po b/lang/python/az_AZ/LC_MESSAGES/python.po index 5fdf99797..4fb1f949b 100644 --- a/lang/python/az_AZ/LC_MESSAGES/python.po +++ b/lang/python/az_AZ/LC_MESSAGES/python.po @@ -206,6 +206,8 @@ msgid "" "The displaymanagers list is empty or undefined in both globalstorage and " "displaymanager.conf." msgstr "" +"Ekran menecerləri siyahısı həm qlobal yaddaşda, həm də displaymanager.conf-" +"da boşdur və ya təyin olunmamışdır." #: src/modules/displaymanager/main.py:977 msgid "Display manager configuration was incomplete" @@ -318,11 +320,11 @@ msgstr "Aparat saatını ayarlamaq." #: src/modules/mkinitfs/main.py:27 msgid "Creating initramfs with mkinitfs." -msgstr "mkinitfs ilə initramfs yaradılır." +msgstr "mkinitfs ilə initramfs yaradılır" #: src/modules/mkinitfs/main.py:49 msgid "Failed to run mkinitfs on the target" -msgstr "Hədəfdə dracut başladılmadı" +msgstr "Hədəfdə mkinitfs başlatmaq baş tutmadı" #: src/modules/mkinitfs/main.py:50 src/modules/dracut/main.py:50 msgid "The exit code was {}" diff --git a/lang/python/ko/LC_MESSAGES/python.po b/lang/python/ko/LC_MESSAGES/python.po index 7108fb0e0..8b8a891e8 100644 --- a/lang/python/ko/LC_MESSAGES/python.po +++ b/lang/python/ko/LC_MESSAGES/python.po @@ -4,7 +4,7 @@ # FIRST AUTHOR , YEAR. # # Translators: -# 김지현 , 2018 +# Ji-Hyeon Gim , 2018 # JungHee Lee , 2020 # #, fuzzy From 356e13ae93db83c83e77934387f75520a4470c2c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 3 Nov 2020 23:46:07 +0100 Subject: [PATCH 57/72] [partition] Improve logging readability --- src/modules/partition/gui/EditExistingPartitionDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp index 1e66c539c..39900430b 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/gui/EditExistingPartitionDialog.cpp @@ -136,8 +136,8 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) bool partResizedMoved = newFirstSector != m_partition->firstSector() || newLastSector != m_partition->lastSector(); cDebug() << "old boundaries:" << m_partition->firstSector() << m_partition->lastSector() << m_partition->length(); - cDebug() << "new boundaries:" << newFirstSector << newLastSector; - cDebug() << "dirty status:" << m_partitionSizeController->isDirty(); + cDebug() << Logger::SubEntry << "new boundaries:" << newFirstSector << newLastSector; + cDebug() << Logger::SubEntry << "dirty status:" << m_partitionSizeController->isDirty(); FileSystem::Type fsType = FileSystem::Unknown; if ( m_ui->formatRadioButton->isChecked() ) From 87c77d9807f428992e854d48e82b1fa53bee6266 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 00:14:05 +0100 Subject: [PATCH 58/72] [partition] When flags are explicitly invalid, return early --- src/modules/partition/core/PartitionInfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/partition/core/PartitionInfo.cpp b/src/modules/partition/core/PartitionInfo.cpp index 87aa03b66..9ab59ecf3 100644 --- a/src/modules/partition/core/PartitionInfo.cpp +++ b/src/modules/partition/core/PartitionInfo.cpp @@ -52,6 +52,10 @@ PartitionTable::Flags flags( const Partition* partition ) { auto v = partition->property( FLAGS_PROPERTY ); + if ( !v.isValid() ) + { + return partition->activeFlags(); + } if ( v.type() == QVariant::Int ) { return static_cast< PartitionTable::Flags >( v.toInt() ); From 63964de4bdc4ab595570454c4681a162715ba840 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 00:32:21 +0100 Subject: [PATCH 59/72] [partition] Explain underlying type for flags variant --- src/modules/partition/core/PartitionInfo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/partition/core/PartitionInfo.cpp b/src/modules/partition/core/PartitionInfo.cpp index 9ab59ecf3..c4d239db8 100644 --- a/src/modules/partition/core/PartitionInfo.cpp +++ b/src/modules/partition/core/PartitionInfo.cpp @@ -56,7 +56,11 @@ flags( const Partition* partition ) { return partition->activeFlags(); } - if ( v.type() == QVariant::Int ) + // The underlying type of PartitionTable::Flags can be int or uint + // (see qflags.h) and so setting those flags can create a QVariant + // of those types; we don't just want to check QVariant::canConvert() + // here because that will also accept QByteArray and some other things. + if ( v.type() == QVariant::Int || v.type() == QVariant::UInt ) { return static_cast< PartitionTable::Flags >( v.toInt() ); } From 949e33f1e8d7573c5691a2c907f62525e4118616 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 00:43:32 +0100 Subject: [PATCH 60/72] [partition] Massage logging while checking for EFI boot --- src/modules/partition/core/PartUtils.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 07ab5acc1..bbf63e79d 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -439,10 +439,8 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath(); - cDebug() << Logger::SubEntry << "flags" << candidate->activeFlags(); - auto flags = PartitionInfo::flags( candidate ); + cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath() << "flags" << flags; /* If bit 17 is set, old-style Esp flag, it's OK */ if ( flags.testFlag( KPM_PARTITION_FLAG_ESP ) ) @@ -455,19 +453,28 @@ isEfiBootable( const Partition* candidate ) while ( root && !root->isRoot() ) { root = root->parent(); - cDebug() << Logger::SubEntry << "moved towards root" << Logger::Pointer( root ); } // Strange case: no root found, no partition table node? if ( !root ) { + cWarning() << "No root of partition table found."; return false; } const PartitionTable* table = dynamic_cast< const PartitionTable* >( root ); - cDebug() << Logger::SubEntry << "partition table" << Logger::Pointer( table ) << "type" - << ( table ? table->type() : PartitionTable::TableType::unknownTableType ); - return table && ( table->type() == PartitionTable::TableType::gpt ) && flags.testFlag( KPM_PARTITION_FLAG( Boot ) ); + if ( !table ) + { + cWarning() << "Root of partition table is not a PartitionTable object"; + return false; + } + if ( table->type() == PartitionTable::TableType::gpt ) + { + const auto bootFlag = KPM_PARTITION_FLAG( Boot ); + cDebug() << Logger::SubEntry << "GPT table" << flags << "boot?" << bootFlag << flags.testFlag( bootFlag ); + return flags.testFlag( bootFlag ); + } + return false; } QString From 85bb8c27b3437a6ecd63d002071e3760c17091b8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 00:58:11 +0100 Subject: [PATCH 61/72] [partition] Simplify flags calculations - factor out the flags-we-want from the flags-we-already-have - the use of ->activeFlags() meant that the state on *disk* was being compared with the flags-we-want; if a partition was re-edited, then you couldn't change the flags back to the state-on-disk (eg. enable a flag, then change your mind and disable it). - set the flags before refreshing the partition, because the refresh checks for EFI bootability and that needs the new flags, not the old ones. --- .../gui/EditExistingPartitionDialog.cpp | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp index 39900430b..3de6e0c4c 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/gui/EditExistingPartitionDialog.cpp @@ -147,6 +147,9 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) : FileSystem::typeForName( m_ui->fileSystemComboBox->currentText() ); } + const auto resultFlags = newFlags(); + const auto currentFlags = PartitionInfo::flags( m_partition ); + if ( partResizedMoved ) { if ( m_ui->formatRadioButton->isChecked() ) @@ -157,20 +160,20 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) fsType, newFirstSector, newLastSector, - newFlags() ); + resultFlags ); PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); PartitionInfo::setFormat( newPartition, true ); core->deletePartition( m_device, m_partition ); core->createPartition( m_device, newPartition ); - core->setPartitionFlags( m_device, newPartition, newFlags() ); + core->setPartitionFlags( m_device, newPartition, resultFlags ); } else { core->resizePartition( m_device, m_partition, newFirstSector, newLastSector ); - if ( m_partition->activeFlags() != newFlags() ) + if ( currentFlags != resultFlags ) { - core->setPartitionFlags( m_device, m_partition, newFlags() ); + core->setPartitionFlags( m_device, m_partition, resultFlags ); } } } @@ -183,9 +186,9 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) if ( m_partition->fileSystem().type() == fsType ) { core->formatPartition( m_device, m_partition ); - if ( m_partition->activeFlags() != newFlags() ) + if ( currentFlags != resultFlags ) { - core->setPartitionFlags( m_device, m_partition, newFlags() ); + core->setPartitionFlags( m_device, m_partition, resultFlags ); } } else // otherwise, we delete and recreate the partition with new fs type @@ -196,22 +199,22 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) fsType, m_partition->firstSector(), m_partition->lastSector(), - newFlags() ); + resultFlags ); PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); PartitionInfo::setFormat( newPartition, true ); core->deletePartition( m_device, m_partition ); core->createPartition( m_device, newPartition ); - core->setPartitionFlags( m_device, newPartition, newFlags() ); + core->setPartitionFlags( m_device, newPartition, resultFlags ); } } else { - core->refreshPartition( m_device, m_partition ); - if ( m_partition->activeFlags() != newFlags() ) + if ( currentFlags != resultFlags ) { - core->setPartitionFlags( m_device, m_partition, newFlags() ); + core->setPartitionFlags( m_device, m_partition, resultFlags ); } + core->refreshPartition( m_device, m_partition ); } } } From 15ace5202df15390cea1d9af039dc753894af8b8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 01:16:36 +0100 Subject: [PATCH 62/72] [partition] Simplify EFI-flags checking with KPMCore 4 --- src/modules/partition/core/PartUtils.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index bbf63e79d..5cd68c5bf 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -439,9 +439,13 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - auto flags = PartitionInfo::flags( candidate ); - cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath() << "flags" << flags; + const auto flags = PartitionInfo::flags( candidate ); + // TODO: with KPMCore 4, this comment is wrong: the flags + // are remapped, and the ESP flag is the same as Boot. +#if defined( WITH_KPMCORE4API ) + return flags.testFlag( KPM_PARTITION_FLAG_ESP ); +#else /* If bit 17 is set, old-style Esp flag, it's OK */ if ( flags.testFlag( KPM_PARTITION_FLAG_ESP ) ) { @@ -471,10 +475,10 @@ isEfiBootable( const Partition* candidate ) if ( table->type() == PartitionTable::TableType::gpt ) { const auto bootFlag = KPM_PARTITION_FLAG( Boot ); - cDebug() << Logger::SubEntry << "GPT table" << flags << "boot?" << bootFlag << flags.testFlag( bootFlag ); return flags.testFlag( bootFlag ); } return false; +#endif } QString From 0f38ee624ec77a4c8091bb53385a6fccf337d785 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 09:59:35 +0100 Subject: [PATCH 63/72] [partition] static-assert that our shortcut makes sense --- src/modules/partition/core/PartUtils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 5cd68c5bf..92bcbace0 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -444,6 +444,7 @@ isEfiBootable( const Partition* candidate ) // TODO: with KPMCore 4, this comment is wrong: the flags // are remapped, and the ESP flag is the same as Boot. #if defined( WITH_KPMCORE4API ) + static_assert( KPM_PARTITION_FLAG_ESP == KPM_PARTITION_FLAG( Boot ), "KPMCore API enum changed" ); return flags.testFlag( KPM_PARTITION_FLAG_ESP ); #else /* If bit 17 is set, old-style Esp flag, it's OK */ From 2c297a068feb1cd60a1c3ea46f04803601c57b6c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 12:32:51 +0100 Subject: [PATCH 64/72] [partition] Log when an EFI problem has been solved --- src/modules/partition/core/PartitionCoreModule.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index 14ce48b88..254d007c1 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -716,6 +716,8 @@ PartitionCoreModule::updateIsDirty() void PartitionCoreModule::scanForEfiSystemPartitions() { + const bool wasEmpty = m_efiSystemPartitions.isEmpty(); + m_efiSystemPartitions.clear(); QList< Device* > devices; @@ -732,6 +734,11 @@ PartitionCoreModule::scanForEfiSystemPartitions() { cWarning() << "system is EFI but no EFI system partitions found."; } + else if ( wasEmpty ) + { + // But it isn't empty anymore, so whatever problem has been solved + cDebug() << "system is EFI and new EFI system partition has been found."; + } m_efiSystemPartitions = efiSystemPartitions; } From 3e51d77782d7684045ec325d8b62b2e809c429b5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 13:39:23 +0100 Subject: [PATCH 65/72] [keyboard] Check for successful file-write --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 419d6f3fc..8a9f5fe38 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -210,7 +210,11 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const } // Write out the existing lines and replace the KEYMAP= line - file.open( QIODevice::WriteOnly | QIODevice::Text ); + if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + cError() << "Could not open" << file.fileName() << "for writing."; + return false; + } QTextStream stream( &file ); bool found = false; foreach ( const QString& existingLine, existingLines ) @@ -243,7 +247,11 @@ bool SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const { QFile file( keyboardConfPath ); - file.open( QIODevice::WriteOnly | QIODevice::Text ); + if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + cError() << "Could not open" << file.fileName() << "for writing."; + return false; + } QTextStream stream( &file ); stream << "# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" From 845fb3f6da8894f40f2966253a847320ffac31fa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 14:03:14 +0100 Subject: [PATCH 66/72] [keyboard] Refactor writing-various-files - put the writing of each kind of file in its own block -- this should become separate functions -- so that variables become more local and debugging can be improved. - while here, fix the error message for /etc/default/keyboard: it would complain and name the vconsole file path if it ever failed. --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 103 ++++++++++-------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 8a9f5fe38..78459d190 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -337,60 +337,73 @@ SetKeyboardLayoutJob::exec() Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); QDir destDir( gs->value( "rootMountPoint" ).toString() ); - // Get the path to the destination's /etc/vconsole.conf - QString vconsoleConfPath = destDir.absoluteFilePath( "etc/vconsole.conf" ); - - // Get the path to the destination's /etc/X11/xorg.conf.d/00-keyboard.conf - QString xorgConfDPath; - QString keyboardConfPath; - if ( QDir::isAbsolutePath( m_xOrgConfFileName ) ) { - keyboardConfPath = m_xOrgConfFileName; - while ( keyboardConfPath.startsWith( '/' ) ) + // Get the path to the destination's /etc/vconsole.conf + QString vconsoleConfPath = destDir.absoluteFilePath( "etc/vconsole.conf" ); + + // Get the path to the destination's path to the converted key mappings + QString convertedKeymapPath = m_convertedKeymapPath; + if ( !convertedKeymapPath.isEmpty() ) { - keyboardConfPath.remove( 0, 1 ); + while ( convertedKeymapPath.startsWith( '/' ) ) + { + convertedKeymapPath.remove( 0, 1 ); + } + convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPath ); } - keyboardConfPath = destDir.absoluteFilePath( keyboardConfPath ); - xorgConfDPath = QFileInfo( keyboardConfPath ).path(); - } - else - { - xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); - keyboardConfPath = QDir( xorgConfDPath ).absoluteFilePath( m_xOrgConfFileName ); - } - destDir.mkpath( xorgConfDPath ); - QString defaultKeyboardPath; - if ( QDir( destDir.absoluteFilePath( "etc/default" ) ).exists() ) - { - defaultKeyboardPath = destDir.absoluteFilePath( "etc/default/keyboard" ); - } - - // Get the path to the destination's path to the converted key mappings - QString convertedKeymapPath = m_convertedKeymapPath; - if ( !convertedKeymapPath.isEmpty() ) - { - while ( convertedKeymapPath.startsWith( '/' ) ) + cDebug() << "Writing VCONSOLE data to" << vconsoleConfPath << convertedKeymapPath; + if ( !writeVConsoleData( vconsoleConfPath, convertedKeymapPath ) ) { - convertedKeymapPath.remove( 0, 1 ); + return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for the virtual console." ), + tr( "Failed to write to %1" ).arg( vconsoleConfPath ) ); } - convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPath ); } - if ( !writeVConsoleData( vconsoleConfPath, convertedKeymapPath ) ) - return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for the virtual console." ), - tr( "Failed to write to %1" ).arg( vconsoleConfPath ) ); - - if ( !writeX11Data( keyboardConfPath ) ) - return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for X11." ), - tr( "Failed to write to %1" ).arg( keyboardConfPath ) ); - - if ( !defaultKeyboardPath.isEmpty() && m_writeEtcDefaultKeyboard ) { - if ( !writeDefaultKeyboardData( defaultKeyboardPath ) ) - return Calamares::JobResult::error( - tr( "Failed to write keyboard configuration to existing /etc/default directory." ), - tr( "Failed to write to %1" ).arg( keyboardConfPath ) ); + // Get the path to the destination's /etc/X11/xorg.conf.d/00-keyboard.conf + QString xorgConfDPath; + QString keyboardConfPath; + if ( QDir::isAbsolutePath( m_xOrgConfFileName ) ) + { + keyboardConfPath = m_xOrgConfFileName; + while ( keyboardConfPath.startsWith( '/' ) ) + { + keyboardConfPath.remove( 0, 1 ); + } + keyboardConfPath = destDir.absoluteFilePath( keyboardConfPath ); + xorgConfDPath = QFileInfo( keyboardConfPath ).path(); + } + else + { + xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); + keyboardConfPath = QDir( xorgConfDPath ).absoluteFilePath( m_xOrgConfFileName ); + } + destDir.mkpath( xorgConfDPath ); + + if ( !writeX11Data( keyboardConfPath ) ) + { + return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for X11." ), + tr( "Failed to write to %1" ).arg( keyboardConfPath ) ); + } + } + + { + QString defaultKeyboardPath; + if ( QDir( destDir.absoluteFilePath( "etc/default" ) ).exists() ) + { + defaultKeyboardPath = destDir.absoluteFilePath( "etc/default/keyboard" ); + } + + if ( !defaultKeyboardPath.isEmpty() && m_writeEtcDefaultKeyboard ) + { + if ( !writeDefaultKeyboardData( defaultKeyboardPath ) ) + { + return Calamares::JobResult::error( + tr( "Failed to write keyboard configuration to existing /etc/default directory." ), + tr( "Failed to write to %1" ).arg( defaultKeyboardPath ) ); + } + } } return Calamares::JobResult::ok(); From e9e4be1c60ec8adcf3a16fb98ae9a48a5b5e2e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Tue, 3 Nov 2020 16:53:21 -0500 Subject: [PATCH 67/72] [umount] Fix list of mount-points to unmount The root mount-point can end with a / while the mount-point read from the file /etc/mtab does not end with a /. This leads to skip the unmounting of the root mount-point and causes the removal of the root mountpoint directory to fail with EBUSY because it is still mounted. This uses the python functions os.path.normpath() to normalize the root mount-point (i.e. to drop the trailing /) and os.path.commonprefix() to determine the longest common prefix between the two mount-points. If the returned prefix is identical to the normalized root mount-point then the mount-point must be added to the list of the mount-points to unmount. More generally, the python modules should rely on the os.path functions to compare for paths instead of using strings. It covers this way lots of corner cases (path with "//", "/../", "/./", ...). --- src/modules/umount/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/umount/main.py b/src/modules/umount/main.py index 86ab1599a..0035a6b0f 100644 --- a/src/modules/umount/main.py +++ b/src/modules/umount/main.py @@ -39,10 +39,11 @@ def list_mounts(root_mount_point): """ lst = [] + root_mount_point = os.path.normpath(root_mount_point) for line in open("/etc/mtab").readlines(): device, mount_point, _ = line.split(" ", 2) - if mount_point.startswith(root_mount_point): + if os.path.commonprefix([root_mount_point, mount_point]) == root_mount_point: lst.append((device, mount_point)) return lst From e2b00bc51798a3a0b77c77744874f960e5e84412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Wed, 4 Nov 2020 09:56:06 -0500 Subject: [PATCH 68/72] [partition] Fix typo --- src/modules/partition/jobs/FillGlobalStorageJob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index c9040877d..5384cf243 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -105,7 +105,7 @@ mapForPartition( Partition* partition, const QString& uuid ) using TR = Logger::DebugRow< const char* const, const QString& >; deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode() << TR( "partlabel", map[ "partlabel" ].toString() ) << TR( "partuuid", map[ "partuuid" ].toString() ) - << TR( "parttype", map[ "partype" ].toString() ) << TR( "partattrs", map[ "partattrs" ].toString() ) + << TR( "parttype", map[ "parttype" ].toString() ) << TR( "partattrs", map[ "partattrs" ].toString() ) << TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) << TR( "fs:", map[ "fs" ].toString() ) << TR( "fsName", map[ "fsName" ].toString() ) << TR( "uuid", uuid ) << TR( "claimed", map[ "claimed" ].toString() ); From 57da222c7231bce0d7903218e864593001c0519d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 16:16:28 +0100 Subject: [PATCH 69/72] [keyboard] Improve debug-logging for vconsole-config --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 78459d190..331c11efb 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -179,6 +179,8 @@ SetKeyboardLayoutJob::findLegacyKeymap() const bool SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const QString& convertedKeymapPath ) const { + cDebug() << "Writing vconsole data to" << vconsoleConfPath; + QString keymap = findConvertedKeymap( convertedKeymapPath ); if ( keymap.isEmpty() ) { @@ -205,6 +207,7 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const file.close(); if ( stream.status() != QTextStream::Ok ) { + cError() << "Could not read lines from" << file.fileName(); return false; } } @@ -217,7 +220,7 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const } QTextStream stream( &file ); bool found = false; - foreach ( const QString& existingLine, existingLines ) + for( const QString& existingLine : qAsConst( existingLines ) ) { if ( existingLine.trimmed().startsWith( "KEYMAP=" ) ) { @@ -237,7 +240,7 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const stream.flush(); file.close(); - cDebug() << "Written KEYMAP=" << keymap << "to vconsole.conf"; + cDebug() << Logger::SubEntry << "Written KEYMAP=" << keymap << "to vconsole.conf" << stream.status(); return ( stream.status() == QTextStream::Ok ); } @@ -352,7 +355,6 @@ SetKeyboardLayoutJob::exec() convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPath ); } - cDebug() << "Writing VCONSOLE data to" << vconsoleConfPath << convertedKeymapPath; if ( !writeVConsoleData( vconsoleConfPath, convertedKeymapPath ) ) { return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for the virtual console." ), From cbc376a20666e9aab57f9eae46ae5d1b2ca4bd42 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 16:29:57 +0100 Subject: [PATCH 70/72] [keyboard] Improve debug-logging for writing X11 config --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 331c11efb..2588608b1 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -249,6 +249,8 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const bool SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const { + cDebug() << "Writing X11 configuration to" << keyboardConfPath; + QFile file( keyboardConfPath ); if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) { @@ -298,8 +300,8 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const file.close(); - cDebug() << "Written XkbLayout" << m_layout << "; XkbModel" << m_model << "; XkbVariant" << m_variant - << "to X.org file" << keyboardConfPath; + cDebug() << Logger::SubEntry << "Written XkbLayout" << m_layout << "; XkbModel" << m_model << "; XkbVariant" << m_variant + << "to X.org file" << keyboardConfPath << stream.status(); return ( stream.status() == QTextStream::Ok ); } From 705e6dd8d697769000e3a77bfd6a88474a672ea9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 16:31:35 +0100 Subject: [PATCH 71/72] [keyboard] Improve debug-logging for writing etc/default --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 2588608b1..9cf76d96b 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -310,8 +310,14 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const bool SetKeyboardLayoutJob::writeDefaultKeyboardData( const QString& defaultKeyboardPath ) const { + cDebug() << "Writing default keyboard data to" << defaultKeyboardPath; + QFile file( defaultKeyboardPath ); - file.open( QIODevice::WriteOnly | QIODevice::Text ); + if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + cError() << "Could not open" << defaultKeyboardPath << "for writing"; + return false; + } QTextStream stream( &file ); stream << "# KEYBOARD CONFIGURATION FILE\n\n" @@ -326,8 +332,8 @@ SetKeyboardLayoutJob::writeDefaultKeyboardData( const QString& defaultKeyboardPa file.close(); - cDebug() << "Written XKBMODEL" << m_model << "; XKBLAYOUT" << m_layout << "; XKBVARIANT" << m_variant - << "to /etc/default/keyboard file" << defaultKeyboardPath; + cDebug() << Logger::SubEntry << "Written XKBMODEL" << m_model << "; XKBLAYOUT" << m_layout << "; XKBVARIANT" << m_variant + << "to /etc/default/keyboard file" << defaultKeyboardPath << stream.status(); return ( stream.status() == QTextStream::Ok ); } From 83d2c06f68540cc16bdcf8e1f4425a35a030ffd0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 4 Nov 2020 16:36:52 +0100 Subject: [PATCH 72/72] [keyboard] Apply coding style --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 9cf76d96b..c80d84e7d 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -220,7 +220,7 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, const } QTextStream stream( &file ); bool found = false; - for( const QString& existingLine : qAsConst( existingLines ) ) + for ( const QString& existingLine : qAsConst( existingLines ) ) { if ( existingLine.trimmed().startsWith( "KEYMAP=" ) ) { @@ -300,8 +300,8 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const file.close(); - cDebug() << Logger::SubEntry << "Written XkbLayout" << m_layout << "; XkbModel" << m_model << "; XkbVariant" << m_variant - << "to X.org file" << keyboardConfPath << stream.status(); + cDebug() << Logger::SubEntry << "Written XkbLayout" << m_layout << "; XkbModel" << m_model << "; XkbVariant" + << m_variant << "to X.org file" << keyboardConfPath << stream.status(); return ( stream.status() == QTextStream::Ok ); } @@ -332,8 +332,8 @@ SetKeyboardLayoutJob::writeDefaultKeyboardData( const QString& defaultKeyboardPa file.close(); - cDebug() << Logger::SubEntry << "Written XKBMODEL" << m_model << "; XKBLAYOUT" << m_layout << "; XKBVARIANT" << m_variant - << "to /etc/default/keyboard file" << defaultKeyboardPath << stream.status(); + cDebug() << Logger::SubEntry << "Written XKBMODEL" << m_model << "; XKBLAYOUT" << m_layout << "; XKBVARIANT" + << m_variant << "to /etc/default/keyboard file" << defaultKeyboardPath << stream.status(); return ( stream.status() == QTextStream::Ok ); }