source: src-qt4/pc-updatecenter/syscontroller.cpp @ 08cf0aa

releng/10.0releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since 08cf0aa was 08cf0aa, checked in by yurkis <yurkis@…>, 8 months ago

Add base system update history view window. Work was started for getting current base system update description (yet undone)

  • Property mode set to 100644
File size: 16.3 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2013- by Yuri Momotyuk                                   *
3*   yurkis@gmail.com                                                      *
4*                                                                         *
5*   Permission is hereby granted, free of charge, to any person obtaining *
6*   a copy of this software and associated documentation files (the       *
7*   "Software"), to deal in the Software without restriction, including   *
8*   without limitation the rights to use, copy, modify, merge, publish,   *
9*   distribute, sublicense, and/or sell copies of the Software, and to    *
10*   permit persons to whom the Software is furnished to do so, subject to *
11*   the following conditions:                                             *
12*                                                                         *
13*   The above copyright notice and this permission notice shall be        *
14*   included in all copies or substantial portions of the Software.       *
15*                                                                         *
16*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
17*   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
18*   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
19*   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
20*   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
21*   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
22*   OTHER DEALINGS IN THE SOFTWARE.                                       *
23***************************************************************************/
24
25#include "syscontroller.h"
26#include "utils.h"
27#include "pcbsd-utils.h"
28#include <QDebug>
29#include <QRegExp>
30
31__string_constant PC_UPDATE_COMMAND = "pc-updatemanager";
32//_STRING_CONSTANT FBSD_UPDATE_COMMAND = "cat";
33__string_constant FBSD_UPDATE_COMMAND = "pc-fbsdupdatecheck";
34static const QStringList PC_UPDATE_ARGS(QStringList()<<"check");
35static const QStringList FBSD_UPDATE_ARGS (QStringList()<<"update");
36//static const QStringList FBSD_UPDATE_ARGS (QStringList()<<"/home/yurkis/_sysbasesys_check.txt");
37
38__string_constant NAME_TAG = "NAME:";
39__string_constant TYPE_TAG = "TYPE:";
40__string_constant TAG_TAG = "TAG:";
41__string_constant VERSION_TAG = "VERSION:";
42__string_constant DEATILS_TAG = "DETAILS:";
43__string_constant DATE_TAG = "DATE:";
44__string_constant SIZE_TAG = "SIZE:";
45__string_constant CU_END_MARKER = "To install:";
46__string_constant PATCH_TYPE = "PATCH";
47__string_constant SYSUPDATE_TYPE = "SYSUPDATE";
48__string_constant STANDALONE_TAG = "STANDALONE:";
49__string_constant REQUIRESREBOOT_TAG = "REQUIRESREBOOT:";
50
51__string_constant FILES_MODIFYED_LOCALLY = "been downloaded because the files have been modified locally:";
52__string_constant FILES_TO_DELETE = "The following files will be removed as part of updating to";
53__string_constant FILES_TO_UPDATE = "The following files will be updated as part of updating to";
54
55__string_constant NETWORKING_PROBLEM= "No mirrors remaining, giving up.";
56
57__string_constant SYS_PATCH_DOWNLOADING_WORD= "DOWNLOADING:";
58__string_constant SYS_PATCH_FETCH= "FETCH";
59__string_constant SYS_PATCH_DL_FINISHED= "DOWNLOADFINISHED:";
60__string_constant SYS_PATCH_TOTAL_STEPS= "TOTALSTEPS:";
61__string_constant SYS_PATCH_SETSTEPS= "SETSTEPS:";
62__string_constant SYS_PATCH_MSG= "MSG:";
63__string_constant SYS_PATCH_FINISHED= "INSTALLFINISHED:";
64
65__string_constant UPDATE_DESCRIPTIONS_FETCH_COMMAND = "fetch -q -o-";
66__string_constant UPDATE_DESCRIPTIONS_URL = "http://fbsd-update.pcbsd.org/updates.desc";
67__string_constant UPDATE_DESCRIPTIONS_FIELDS_SEPARATOR = ":::";
68
69__string_constant FILES_REQUIRED_REBOOT []= { "/boot/*", "/usr/lib/libc*" };
70
71const int FILES_REQUIRED_REBOOT_SIZE = sizeof(FILES_REQUIRED_REBOOT) / sizeof(char*);
72
73///////////////////////////////////////////////////////////////////////////////
74CSysController::CSysController()
75{
76    misFREEBSDCheck= false;
77
78    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
79    env.insert("PCFETCHGUI", "YES");
80    process().setProcessEnvironment(env);
81    misFBSDRebootRequired= false;
82    misRebootRequired = false;
83}
84
85///////////////////////////////////////////////////////////////////////////////
86bool CSysController::rebootRequired()
87{
88    return misRebootRequired && (currentState()!= eUPDATING);
89}
90
91///////////////////////////////////////////////////////////////////////////////
92QVector<CSysController::SFbsdUpdatesDescription> CSysController::updateDescriptions(QString RelName, bool isForse)
93{
94    QVector<CSysController::SFbsdUpdatesDescription> out;
95
96    QStringList fetch_out = pcbsd::Utils::runShellCommand(QString(UPDATE_DESCRIPTIONS_FETCH_COMMAND) + " " + UPDATE_DESCRIPTIONS_URL);
97
98    if (!mvFbsdUpdateDescriptions.size() || isForse)
99    {
100        mvFbsdUpdateDescriptions.clear();
101        for (int i=0; i<fetch_out.size(); i++)
102        {
103            SFbsdUpdatesDescription entry;
104            QStringList line_split = fetch_out[i].split(UPDATE_DESCRIPTIONS_FIELDS_SEPARATOR);
105            if (line_split.size() < 3)
106                continue;
107            entry.mRelease = line_split[0];
108            entry.mDescription = line_split[2];
109            entry.mUpdateNo = line_split[1].toInt();
110            mvFbsdUpdateDescriptions.push_back(entry);
111        }
112    }
113
114    //filter by RelName
115    for (int i=0; i<mvFbsdUpdateDescriptions.size(); i++)
116    {
117        if ((!RelName.length()) || RelName.trimmed().toUpper() == mvFbsdUpdateDescriptions[i].mRelease.trimmed().toUpper() )
118        {
119            out.push_back(mvFbsdUpdateDescriptions[i]);
120        }
121    }
122    return out;
123}
124
125///////////////////////////////////////////////////////////////////////////////
126void CSysController::updateSelected(QVector<CSysController::SSystemUpdate> selectedUpdates)
127{
128    mvUpdatesToApply= selectedUpdates;
129    mCurrentUpdate= 0;
130    launchUpdate();
131}
132
133///////////////////////////////////////////////////////////////////////////////
134void CSysController::onCheckUpdates()
135{
136    misFREEBSDCheck= false;
137    mvUpdates.clear();
138    mFilesLocallyModifyed.clear();
139    mFilesToRemove.clear();
140    mFilesToUpdate.clear();
141}
142
143///////////////////////////////////////////////////////////////////////////////
144void CSysController::onUpdateAll()
145{
146    mvUpdatesToApply = mvUpdates;
147    mCurrentUpdate= 0;
148    launchUpdate();
149}
150
151///////////////////////////////////////////////////////////////////////////////
152void CSysController::checkShellCommand(QString &cmd, QStringList &args)
153{
154    if (misFREEBSDCheck)
155    {
156        cmd= FBSD_UPDATE_COMMAND;
157        args= FBSD_UPDATE_ARGS;
158    }
159    else
160    {
161        cmd= PC_UPDATE_COMMAND;
162        args= PC_UPDATE_ARGS;
163    }
164}
165
166///////////////////////////////////////////////////////////////////////////////
167void CSysController::updateShellCommand(QString &cmd, QStringList &args)
168{
169    if (mCurrentUpdate>=mvUpdatesToApply.size())
170        return;
171
172    ESysUpdate currUpdateType= mvUpdatesToApply[mCurrentUpdate].mType;
173    if ((currUpdateType == ePATCH) || (currUpdateType == eSYSUPDATE))
174    {
175        cmd= PC_UPDATE_COMMAND;
176        args= QStringList()<<"install"<<mvUpdatesToApply[mCurrentUpdate].mTag;
177    }
178    else
179    {
180        cmd="freebsd-update";
181        args= QStringList()<<"install";
182    }
183
184}
185
186///////////////////////////////////////////////////////////////////////////////
187void CSysController::onReadCheckLine(QString line)
188{   
189    if (misFREEBSDCheck)
190        parseCheckFREEBSDLine(line);
191    else
192        parseCheckPCBSDLine(line);
193
194}
195
196///////////////////////////////////////////////////////////////////////////////
197void CSysController::onReadUpdateLine(QString line)
198{
199    line= line.trimmed();
200    if (mCurrentUpdate>=mvUpdatesToApply.size())
201        return;
202    ESysUpdate currUpdateType= mvUpdatesToApply[mCurrentUpdate].mType;
203    misRebootRequired |= mvUpdatesToApply[mCurrentUpdate].misRequiresReboot;
204
205    switch(currUpdateType)
206    {
207        case ePATCH:
208            parsePatchUpdateLine(line);
209            break;
210        case eSYSUPDATE:
211            parseUpgradeLine(line);
212            break;
213        case eFBSDUPDATE:
214            parseFreeBSDUpdateLine(line);
215            break;
216    }
217}
218
219///////////////////////////////////////////////////////////////////////////////
220void CSysController::onReadProcessChar(char character)
221{
222    qDebug()<<character;
223}
224
225///////////////////////////////////////////////////////////////////////////////
226void CSysController::onCheckProcessfinished(int exitCode)
227{
228    if (!misFREEBSDCheck)
229    {       
230        misFREEBSDCheck= true;
231        misFBSDRebootRequired= false;
232        launchCheck();
233    }
234    else
235    {       
236        if (mFilesToRemove.size() || mFilesToUpdate.size())
237        {
238            SSystemUpdate entry;
239            entry.mName= tr("Base system update");
240            entry.mType= eFBSDUPDATE;
241            entry.misRequiresReboot= misFBSDRebootRequired;
242            mvUpdates.push_back(entry);
243        }
244
245        int n= mvUpdates.size();
246
247        if (n)
248        {
249
250            if (n>1)
251                reportUpdatesAvail(tr("%1 system updates avilable").arg(QString::number(n)));
252            else
253                reportUpdatesAvail(tr("System update is available"));
254            return;
255        }
256        else
257        {
258            if (!exitCode)
259            {
260                setCurrentState(eFULLY_UPDATED);
261            }
262            else
263            {
264                reportError(tr("Error while system update check process"));
265            }
266            return;
267        }
268    }
269}
270
271///////////////////////////////////////////////////////////////////////////////
272void CSysController::onUpdateProcessfinished(int exitCode)
273{
274    Q_UNUSED(exitCode);
275
276    if (currentState() != eUPDATING)
277        return;
278    mCurrentUpdate++;
279    if (mCurrentUpdate == mvUpdatesToApply.size())
280    {
281        if (misRebootRequired)
282        {
283            system("touch /tmp/.fbsdup-reboot");
284        }
285        check();
286    }
287    else
288    {
289        launchUpdate();
290    }
291}
292
293///////////////////////////////////////////////////////////////////////////////
294void CSysController::onCancel()
295{
296    process().terminate();
297    process().waitForFinished();
298    check();
299}
300
301///////////////////////////////////////////////////////////////////////////////
302void CSysController::parseCheckPCBSDLine(QString line)
303{
304    /*if (line == QString("Your system is up to date!"))
305    {
306        setCurrentState(eFULLY_UPDATED);
307    }*/
308    static SSystemUpdate upd;
309    line= line.trimmed();
310
311#define _GET_TAG(tag, field)  if(line.indexOf(tag) == 0) {upd.field = line.replace(tag,""); return;}
312    _GET_TAG(NAME_TAG, mName);
313    _GET_TAG(TAG_TAG, mTag);
314    _GET_TAG(VERSION_TAG, mVersion);
315    _GET_TAG(DEATILS_TAG, mDetails);
316    _GET_TAG(SIZE_TAG, mSize);
317#undef _GET_TAG
318
319    if (line.indexOf(TYPE_TAG) == 0)
320    {
321        line= line.replace(TYPE_TAG, "");
322        if (line.contains(SYSUPDATE_TYPE))
323        {
324            upd.mType = eSYSUPDATE;
325        }
326        else
327        {
328            upd.mType = ePATCH;
329        }
330    }
331
332    if (line.indexOf(DATE_TAG) == 0)
333    {
334        //Example:
335        // DATE: 02-10-2013
336        // x     ^0 ^1 ^2   (m-d-y)?
337        QString y,m,d;
338        line= line.replace(DATE_TAG, "");
339        QStringList line_list = line.split("-");
340        upd.mDate= QDate(line_list[2].toInt(),
341                         line_list[0].toInt(),
342                         line_list[1].toInt());       
343        return;
344    }
345
346    if (line.indexOf(STANDALONE_TAG) == 0)
347    {
348        line= line.replace(STANDALONE_TAG, "");
349        if (line.trimmed().toLower() == "yes")
350            upd.misStandalone= true;
351    }
352
353    if (line.indexOf(REQUIRESREBOOT_TAG) == 0)
354    {
355        line= line.replace(REQUIRESREBOOT_TAG, "");
356        if (line.trimmed().toLower() == "yes")
357            upd.misRequiresReboot= true;
358    }
359
360    if (line.indexOf(CU_END_MARKER) == 0)
361    {
362        mvUpdates.push_back(upd);
363        upd = SSystemUpdate();
364        return;
365    }
366}
367
368///////////////////////////////////////////////////////////////////////////////
369void CSysController::parseCheckFREEBSDLine(QString line)
370{
371    //qDebug()<<line;
372
373    typedef enum{
374        eUndefined,
375        eFilesModifyedLocally,
376        eFilesToDelete,
377        eFilesToUpdate
378    }ECheckState;
379
380    static ECheckState currCheckState = eUndefined;
381
382    line=line.trimmed();
383    if (!line.length())
384    {
385        return;
386    }
387
388    if (line.contains(NETWORKING_PROBLEM) && (!mvUpdates.size()))
389    {
390        reportError(tr("Error during update check. Check network connection"));
391    }
392
393    if (line.contains(FILES_MODIFYED_LOCALLY))
394    {
395        currCheckState= eFilesModifyedLocally;
396        return;
397    }
398    else if (line.contains(FILES_TO_DELETE))
399    {
400        currCheckState= eFilesToDelete;
401        return;
402    }
403    else if (line.contains(FILES_TO_UPDATE))
404    {
405        currCheckState= eFilesToUpdate;
406        return;
407    }
408
409
410    if (eFilesModifyedLocally == currCheckState)
411    {
412        mFilesLocallyModifyed<<line;
413    }
414    else
415    if (eFilesToDelete == currCheckState)
416    {
417        mFilesToRemove<<line;
418    }
419    else
420    if(eFilesToUpdate == currCheckState)
421    {
422        mFilesToUpdate<<line;
423        // Check if reboot requuired.
424        // FILES_REQUIRED_REBOOT const array contains wildcards for files.
425        // Modification of that files requires system reboot
426        QRegExp rx;
427        rx.setPatternSyntax(QRegExp::WildcardUnix);
428        for (int i=0; i<FILES_REQUIRED_REBOOT_SIZE; i++)
429        {
430            rx.setPattern(FILES_REQUIRED_REBOOT[i]);
431            if (rx.exactMatch(line))
432            {
433                misFBSDRebootRequired= true;
434            }//if match
435        }//for all wildcard
436    }
437
438}
439
440///////////////////////////////////////////////////////////////////////////////
441void CSysController::parsePatchUpdateLine(QString line)
442{
443    SProgress progress;
444    static int total_steps = 0;
445    QString dl_speed;
446    long dl_size, dl_complete;
447
448    line= line.trimmed();
449
450    if (line.indexOf(SYS_PATCH_DOWNLOADING_WORD) == 0)
451    {
452        reportLogLine(QString("---------------------"));
453        reportLogLine(QString("Installing update ") + mvUpdatesToApply[mCurrentUpdate].mName);
454        reportLogLine(line.replace(SYS_PATCH_DOWNLOADING_WORD, "Downloading"));
455        progress.mMessage= tr("Preparing to download ") + mvUpdatesToApply[mCurrentUpdate].mName;
456        reportProgress(progress);
457        return;
458    }
459    else
460    if (line.indexOf(SYS_PATCH_FETCH) == 0)
461    {
462        return;
463    }
464    else
465    if (parseFetchOutput(line, dl_size, dl_complete, dl_speed))
466    {
467        progress.mMessage=tr("Downloading update (%1/%2 at %3)").arg(pcbsd::Utils::bytesToHumanReadable(dl_size),
468                                                                   pcbsd::Utils::bytesToHumanReadable(dl_complete),
469                                                                   dl_speed);
470        progress.mProgressMax= dl_size;
471        progress.mProgressCurr= dl_complete;
472        progress.mSubstate= eDownload;
473        progress.misCanCancel= true;
474        reportProgress(progress);
475        return;
476    }
477    else
478    if (line.indexOf(SYS_PATCH_TOTAL_STEPS) == 0)
479    {
480        line.replace(SYS_PATCH_TOTAL_STEPS, "");
481        total_steps= line.toInt();
482        return;
483    }
484    else
485    if (line.indexOf(SYS_PATCH_SETSTEPS) == 0)
486    {
487        line.replace(SYS_PATCH_SETSTEPS, "");
488        progress.mMessage= tr("Installing update ") + mvUpdatesToApply[mCurrentUpdate].mName;
489        progress.mProgressMax= total_steps;
490        progress.mProgressCurr= line.toInt();
491        progress.mSubstate= eInstall;
492        reportProgress(progress);
493        return;
494    }
495    else
496    if (line.indexOf(SYS_PATCH_MSG) == 0)
497    {
498        line.replace(SYS_PATCH_MSG, "");
499        reportLogLine(line);
500        return;
501    }
502    else
503    if (line.indexOf(SYS_PATCH_FINISHED) == 0)
504    {
505        reportLogLine(QString("Finished install: ") + mvUpdatesToApply[mCurrentUpdate].mName);
506        return;
507    }
508
509}
510
511///////////////////////////////////////////////////////////////////////////////
512void CSysController::parseUpgradeLine(QString line)
513{
514    SProgress progress;
515    progress.mMessage = tr("Installing system upgrade");
516    reportProgress(progress);
517    reportLogLine(line);
518}
519
520///////////////////////////////////////////////////////////////////////////////
521void CSysController::parseFreeBSDUpdateLine(QString line)
522{
523    SProgress progress;
524    progress.mMessage = tr("Installing system update");
525    reportProgress(progress);
526    reportLogLine(line);
527}
Note: See TracBrowser for help on using the repository browser.