source: calamares/trunk/fuentes/src/libcalamares/utils/CalamaresUtilsSystem.cpp @ 7538

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

sync with github

File size: 8.5 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014, Teo Mrnjavac <teo@kde.org>
4 *   Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
5 *
6 *   Calamares is free software: you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation, either version 3 of the License, or
9 *   (at your option) any later version.
10 *
11 *   Calamares is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "CalamaresUtilsSystem.h"
21
22#include "utils/Logger.h"
23#include "GlobalStorage.h"
24#include "JobQueue.h"
25#include "Settings.h"
26
27#include <QCoreApplication>
28#include <QDir>
29#include <QProcess>
30#include <QRegularExpression>
31
32#ifdef Q_OS_LINUX
33#include <sys/sysinfo.h>
34#endif
35
36#ifdef Q_OS_FREEBSD
37#include <sys/types.h>
38#include <sys/sysctl.h>
39#endif
40
41namespace CalamaresUtils
42{
43
44System* System::s_instance = nullptr;
45
46
47System::System( bool doChroot, QObject* parent )
48    : QObject( parent )
49    , m_doChroot( doChroot )
50{
51    Q_ASSERT( !s_instance );
52    s_instance = this;
53    if ( !doChroot )
54        Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" );
55}
56
57
58System::~System()
59{}
60
61
62System*
63System::instance()
64{
65    if ( !s_instance )
66    {
67        cError() << "No Calamares system-object has been created.";
68        cError() << " .. using a bogus instance instead.";
69        return new System( true, nullptr );
70    }
71    return s_instance;
72}
73
74
75int
76System::mount( const QString& devicePath,
77       const QString& mountPoint,
78       const QString& filesystemName,
79       const QString& options )
80{
81    if ( devicePath.isEmpty() || mountPoint.isEmpty() )
82        return -3;
83
84    QDir mountPointDir( mountPoint );
85    if ( !mountPointDir.exists() )
86    {
87        bool ok = mountPointDir.mkpath( mountPoint );
88        if ( !ok )
89            return -3;
90    }
91
92    QString program( "mount" );
93    QStringList args = { devicePath, mountPoint };
94
95    if ( !filesystemName.isEmpty() )
96        args << "-t" << filesystemName;
97
98    if ( !options.isEmpty() )
99        args << "-o" << options;
100
101    return QProcess::execute( program, args );
102}
103
104ProcessResult
105System::runCommand(
106    System::RunLocation location,
107    const QStringList& args,
108    const QString& workingPath,
109    const QString& stdInput,
110    int timeoutSec )
111{
112    QString output;
113
114    if ( !Calamares::JobQueue::instance() )
115        return -3;
116
117    Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
118    if ( ( location == System::RunLocation::RunInTarget ) &&
119         ( !gs || !gs->contains( "rootMountPoint" ) ) )
120    {
121        cWarning() << "No rootMountPoint in global storage";
122        return -3;
123    }
124
125    QProcess process;
126    QString program;
127    QStringList arguments;
128
129    if ( location == System::RunLocation::RunInTarget )
130    {
131        QString destDir = gs->value( "rootMountPoint" ).toString();
132        if ( !QDir( destDir ).exists() )
133        {
134            cWarning() << "rootMountPoint points to a dir which does not exist";
135            return -3;
136        }
137
138        program = "chroot";
139        arguments = QStringList( { destDir } );
140        arguments << args;
141    }
142    else
143    {
144        program = "env";
145        arguments << args;
146    }
147
148    process.setProgram( program );
149    process.setArguments( arguments );
150    process.setProcessChannelMode( QProcess::MergedChannels );
151
152    if ( !workingPath.isEmpty() )
153    {
154        if ( QDir( workingPath ).exists() )
155            process.setWorkingDirectory( QDir( workingPath ).absolutePath() );
156        else
157            cWarning() << "Invalid working directory:" << workingPath;
158            return -3;
159    }
160
161    cDebug() << "Running" << program << arguments;
162    process.start();
163    if ( !process.waitForStarted() )
164    {
165        cWarning() << "Process failed to start" << process.error();
166        return -2;
167    }
168
169    if ( !stdInput.isEmpty() )
170    {
171        process.write( stdInput.toLocal8Bit() );
172        process.closeWriteChannel();
173    }
174
175    if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) )
176    {
177        cWarning().noquote().nospace() << "Timed out. Output so far:\n" <<
178            process.readAllStandardOutput();
179        return -4;
180    }
181
182    output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() );
183
184    if ( process.exitStatus() == QProcess::CrashExit )
185    {
186        cWarning().noquote().nospace() << "Process crashed. Output so far:\n" << output;
187        return -1;
188    }
189
190    auto r = process.exitCode();
191    cDebug() << "Finished. Exit code:" << r;
192    if ( ( r != 0 ) || Calamares::Settings::instance()->debugMode() )
193    {
194        cDebug() << "Target cmd:" << args;
195        cDebug().noquote().nospace() << "Target output:\n" << output;
196    }
197    return ProcessResult(r, output);
198}
199
200
201QPair<quint64, float>
202System::getTotalMemoryB() const
203{
204#ifdef Q_OS_LINUX
205    struct sysinfo i;
206    int r = sysinfo( &i );
207
208    if (r)
209        return qMakePair(0, 0.0);
210
211    return qMakePair(quint64( i.mem_unit ) * quint64( i.totalram ), 1.1);
212#elif defined( Q_OS_FREEBSD )
213    unsigned long memsize;
214    size_t s = sizeof(memsize);
215
216    int r = sysctlbyname("vm.kmem_size", &memsize, &s, NULL, 0);
217    if (r)
218        return qMakePair(0, 0.0);
219
220    return qMakePair(memsize, 1.01);
221#else
222    return qMakePair(0, 0.0);  // Unsupported
223#endif
224}
225
226
227QString
228System::getCpuDescription() const
229{
230    QString model;
231
232#ifdef Q_OS_LINUX
233    QFile file("/proc/cpuinfo");
234    if ( file.open(QIODevice::ReadOnly | QIODevice::Text) )
235        while ( !file.atEnd() )
236        {
237            QByteArray line = file.readLine();
238            if ( line.startsWith( "model name" ) && (line.indexOf( ':' ) > 0) )
239            {
240                model = QString::fromLatin1( line.right(line.length() - line.indexOf( ':' ) ) );
241                break;
242            }
243        }
244#elif defined( Q_OS_FREEBSD )
245    // This would use sysctl "hw.model", which has a string value
246#endif
247    return model.simplified();
248}
249
250quint64
251System::getTotalDiskB() const
252{
253    return 0;
254}
255
256bool
257System::doChroot() const
258{
259    return m_doChroot;
260}
261
262Calamares::JobResult
263ProcessResult::explainProcess( int ec, const QString& command, const QString& output, int timeout )
264{
265    using Calamares::JobResult;
266
267    if ( ec == 0 )
268        return JobResult::ok();
269
270    QString outputMessage = output.isEmpty()
271        ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command.")
272        : (QCoreApplication::translate( "ProcessResult", "\nOutput:\n") + output);
273
274    if ( ec == -1 ) //Crash!
275        return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ),
276                                 QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> crashed." )
277                                        .arg( command )
278                                        + outputMessage );
279
280    if ( ec == -2 )
281        return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ),
282                                 QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to start." )
283                                    .arg( command ) );
284
285    if ( ec == -3 )
286        return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ),
287                                 QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) );
288
289    if ( ec == -4 )
290        return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ),
291                                 QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." )
292                                    .arg( command )
293                                    .arg( timeout )
294                                    + outputMessage );
295
296    //Any other exit code
297    return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command finished with errors." ),
298                             QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> finished with exit code %2." )
299                                .arg( command )
300                                .arg( ec )
301                                + outputMessage );
302}
303
304}  // namespace
Note: See TracBrowser for help on using the repository browser.