source: calamares/trunk/fuentes/src/modules/partition/jobs/FillGlobalStorageJob.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 13 months ago

sync with github

File size: 7.9 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014, Aurélien Gâteau <agateau@kde.org>
4 *   Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
5 *   Copyright 2017, Adriaan de Groot <groot@kde.org>
6 *
7 *   Calamares is free software: you can redistribute it and/or modify
8 *   it under the terms of the GNU General Public License as published by
9 *   the Free Software Foundation, either version 3 of the License, or
10 *   (at your option) any later version.
11 *
12 *   Calamares is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "jobs/FillGlobalStorageJob.h"
22
23#include "GlobalStorage.h"
24#include "JobQueue.h"
25#include "core/PartitionInfo.h"
26#include "core/PartitionIterator.h"
27#include "core/KPMHelpers.h"
28#include "Branding.h"
29#include "utils/Logger.h"
30
31// KPMcore
32#include <core/device.h>
33#include <core/partition.h>
34#include <fs/filesystem.h>
35#include <fs/luks.h>
36
37// Qt
38#include <QDebug>
39#include <QDir>
40#include <QFileInfo>
41#include <QProcess>
42
43typedef QHash<QString, QString> UuidForPartitionHash;
44
45static UuidForPartitionHash
46findPartitionUuids( QList < Device* > devices )
47{
48    cDebug() << "Gathering UUIDs for partitions that exist now.";
49    UuidForPartitionHash hash;
50    foreach ( Device* device, devices )
51    {
52        for ( auto it = PartitionIterator::begin( device );
53              it != PartitionIterator::end( device ); ++it )
54        {
55            Partition* p = *it;
56            QString path = p->partitionPath();
57            QString uuid = p->fileSystem().readUUID( p->partitionPath() );
58            hash.insert( path, uuid );
59        }
60    }
61    cDebug() << hash;
62    return hash;
63}
64
65
66static QString
67getLuksUuid( const QString& path )
68{
69    QProcess process;
70    process.setProgram( "cryptsetup" );
71    process.setArguments( { "luksUUID", path } );
72    process.start();
73    process.waitForFinished();
74    if ( process.exitStatus() != QProcess::NormalExit || process.exitCode() )
75        return QString();
76    QString uuid = QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed();
77    return uuid;
78}
79
80
81static QVariant
82mapForPartition( Partition* partition, const QString& uuid )
83{
84    QVariantMap map;
85    map[ "device" ] = partition->partitionPath();
86    map[ "mountPoint" ] = PartitionInfo::mountPoint( partition );
87    map[ "fsName" ] = partition->fileSystem().name();
88    map[ "fs" ] = partition->fileSystem().name( { QStringLiteral("C") } );  // Untranslated
89    if ( partition->fileSystem().type() == FileSystem::Luks &&
90         dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS() )
91        map[ "fs" ] = dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS()->name();
92    map[ "uuid" ] = uuid;
93    cDebug() << partition->partitionPath()
94             << "mtpoint:" << PartitionInfo::mountPoint( partition )
95             << "fs:" << map[ "fs" ] << '(' << map[ "fsName" ] << ')'
96             << uuid;
97
98    if ( partition->roles().has( PartitionRole::Luks ) )
99    {
100        const FileSystem& fsRef = partition->fileSystem();
101        const FS::luks* luksFs = dynamic_cast< const FS::luks* >( &fsRef );
102        if ( luksFs )
103        {
104            map[ "luksMapperName" ] = luksFs->mapperName().split( "/" ).last();
105            map[ "luksUuid" ] = getLuksUuid( partition->partitionPath() );
106            map[ "luksPassphrase" ] = luksFs->passphrase();
107            cDebug() << "luksMapperName:" << map[ "luksMapperName" ];
108        }
109    }
110
111    return map;
112}
113
114FillGlobalStorageJob::FillGlobalStorageJob( QList< Device* > devices, const QString& bootLoaderPath )
115    : m_devices( devices )
116    , m_bootLoaderPath( bootLoaderPath )
117{
118}
119
120QString
121FillGlobalStorageJob::prettyName() const
122{
123    return tr( "Set partition information" );
124}
125
126
127QString
128FillGlobalStorageJob::prettyDescription() const
129{
130    QStringList lines;
131
132    const auto partitionList = createPartitionList().toList();
133    for ( const QVariant &partitionItem : partitionList )
134    {
135        if ( partitionItem.type() == QVariant::Map )
136        {
137            QVariantMap partitionMap = partitionItem.toMap();
138            QString path = partitionMap.value( "device" ).toString();
139            QString mountPoint = partitionMap.value( "mountPoint" ).toString();
140            QString fsType = partitionMap.value( "fs" ).toString();
141            qDebug() << partitionMap.value( "uuid" ) << path << mountPoint << fsType;
142            if ( mountPoint.isEmpty() || fsType.isEmpty() )
143                continue;
144            if ( path.isEmpty() )
145            {
146                if ( mountPoint == "/" )
147                    lines.append( tr( "Install %1 on <strong>new</strong> %2 system partition." )
148                                  .arg( *Calamares::Branding::ShortProductName )
149                                  .arg( fsType ) );
150                else
151                    lines.append( tr( "Set up <strong>new</strong> %2 partition with mount point "
152                                      "<strong>%1</strong>." )
153                                  .arg( mountPoint )
154                                  .arg( fsType ) );
155            }
156            else
157            {
158                if ( mountPoint == "/" )
159                    lines.append( tr( "Install %2 on %3 system partition <strong>%1</strong>." )
160                                  .arg( path )
161                                  .arg( *Calamares::Branding::ShortProductName )
162                                  .arg( fsType ) );
163                else
164                    lines.append( tr( "Set up %3 partition <strong>%1</strong> with mount point "
165                                      "<strong>%2</strong>." )
166                                  .arg( path )
167                                  .arg( mountPoint )
168                                  .arg( fsType ) );
169            }
170        }
171    }
172
173    QVariant bootloaderMap = createBootLoaderMap();
174    if ( !m_bootLoaderPath.isEmpty() )
175    {
176        lines.append( tr( "Install boot loader on <strong>%1</strong>." )
177                      .arg( m_bootLoaderPath ) );
178    }
179    return lines.join( "<br/>" );
180}
181
182
183QString
184FillGlobalStorageJob::prettyStatusMessage() const
185{
186    return tr( "Setting up mount points." );
187}
188
189Calamares::JobResult
190FillGlobalStorageJob::exec()
191{
192    Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage();
193    storage->insert( "partitions", createPartitionList() );
194    if ( !m_bootLoaderPath.isEmpty() )
195    {
196        QVariant var = createBootLoaderMap();
197        if ( !var.isValid() )
198            cDebug() << "Failed to find path for boot loader";
199        cDebug() << "FillGlobalStorageJob writing bootLoader path:" << var;
200        storage->insert( "bootLoader", var );
201    }
202    else
203    {
204        cDebug() << "FillGlobalStorageJob writing empty bootLoader value";
205        storage->insert( "bootLoader", QVariant() );
206    }
207    return Calamares::JobResult::ok();
208}
209
210QVariant
211FillGlobalStorageJob::createPartitionList() const
212{
213    UuidForPartitionHash hash = findPartitionUuids( m_devices );
214    QVariantList lst;
215    cDebug() << "Writing to GlobalStorage[\"partitions\"]";
216    for ( auto device : m_devices )
217    {
218        for ( auto it = PartitionIterator::begin( device );
219              it != PartitionIterator::end( device ); ++it )
220        {
221            lst << mapForPartition( *it, hash.value( ( *it )->partitionPath() ) );
222        }
223    }
224    return lst;
225}
226
227QVariant
228FillGlobalStorageJob::createBootLoaderMap() const
229{
230    QVariantMap map;
231    QString path = m_bootLoaderPath;
232    if ( !path.startsWith( "/dev/" ) )
233    {
234        Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, path );
235        if ( !partition )
236            return QVariant();
237        path = partition->partitionPath();
238    }
239    map[ "installPath" ] = path;
240    return map;
241}
Note: See TracBrowser for help on using the repository browser.