1 | /***************************************************************************
|
---|
2 | xmondorestore.cpp - restore functions
|
---|
3 | -------------------------------------
|
---|
4 | begin : Sun Nov 22 2003
|
---|
5 | copyright : (C) 2003 by Joshua Oreman
|
---|
6 | email : oremanj@get-linux.org
|
---|
7 | cvsid : $Id: xmondorestore.cpp 277 2006-01-03 16:06:12Z bcornec $
|
---|
8 | ***************************************************************************/
|
---|
9 |
|
---|
10 | /***************************************************************************
|
---|
11 | * *
|
---|
12 | * This program is free software; you can redistribute it and/or modify *
|
---|
13 | * it under the terms of the GNU General Public License as published by *
|
---|
14 | * the Free Software Foundation; either version 2 of the License, or *
|
---|
15 | * (at your option) any later version. *
|
---|
16 | * *
|
---|
17 | ***************************************************************************/
|
---|
18 |
|
---|
19 | #include <qbuttongroup.h>
|
---|
20 | #include <qlineedit.h>
|
---|
21 | #include <qlabel.h>
|
---|
22 | #include <qlayout.h>
|
---|
23 | #include <qlistview.h>
|
---|
24 | #include <qstringlist.h>
|
---|
25 | #include <qmessagebox.h>
|
---|
26 |
|
---|
27 | #include "xmondo.h"
|
---|
28 | #include "xmondorestore.h"
|
---|
29 | #include <X-specific.h>
|
---|
30 | extern "C" {
|
---|
31 | #define bool int
|
---|
32 | #include <libmondo-devices-EXT.h>
|
---|
33 | #include <libmondo-filelist-EXT.h>
|
---|
34 | #include <libmondo-files-EXT.h>
|
---|
35 | #include <libmondo-fork-EXT.h>
|
---|
36 | #include <libmondo-tools-EXT.h>
|
---|
37 | #undef bool
|
---|
38 | int restore_everything (struct s_bkpinfo *bkpinfo, struct s_node *filelist);
|
---|
39 | int get_cfg_file_from_archive (struct s_bkpinfo *bkpinfo);
|
---|
40 | int read_cfg_file_into_bkpinfo (char *cfg_file, struct s_bkpinfo *bkpinfo);
|
---|
41 | int mount_cdrom (struct s_bkpinfo *bkpinfo);
|
---|
42 | void setup_MR_global_filenames (struct s_bkpinfo *bkpinfo);
|
---|
43 | extern char *g_mondo_cfg_file;
|
---|
44 | extern char *g_filelist_full;
|
---|
45 | extern int g_current_media_number;
|
---|
46 | extern int g_text_mode;
|
---|
47 | }
|
---|
48 |
|
---|
49 | extern QProgressBar *XMondoProgress;
|
---|
50 | extern QLabel *XMondoProgressWhat, *XMondoProgressWhat2, *XMondoProgressWhat3;
|
---|
51 | extern QCheckBox *XMondoVerbose;
|
---|
52 | extern QMultiLineEdit *XMondoLog;
|
---|
53 | extern QLabel *XMondoStatus;
|
---|
54 | extern QLabel *XMondoTimeTaken, *XMondoTimeToGo, *XMondoProgressPercent;
|
---|
55 | extern QPushButton *XMondoCancel;
|
---|
56 | extern XMEventHolder events;
|
---|
57 |
|
---|
58 | class XMCheckListItem : public QCheckListItem
|
---|
59 | {
|
---|
60 | public:
|
---|
61 | XMCheckListItem (QCheckListItem * parent, const QString & text, Type tt = CheckBox)
|
---|
62 | : QCheckListItem (parent, text, tt), _text (text)
|
---|
63 | {
|
---|
64 | }
|
---|
65 |
|
---|
66 | XMCheckListItem (QListViewItem * parent, const QString & text, Type tt = CheckBox)
|
---|
67 | : QCheckListItem (parent, text, tt), _text (text)
|
---|
68 | {
|
---|
69 | }
|
---|
70 |
|
---|
71 | XMCheckListItem (QListView * parent, const QString & text, Type tt = CheckBox)
|
---|
72 | : QCheckListItem (parent, text, tt), _text (text)
|
---|
73 | {
|
---|
74 | }
|
---|
75 |
|
---|
76 | virtual ~XMCheckListItem() {}
|
---|
77 |
|
---|
78 | virtual int rtti() { return 1001; }
|
---|
79 |
|
---|
80 | virtual void setOn (bool on) {
|
---|
81 | QCheckListItem::setOn (on);
|
---|
82 | }
|
---|
83 |
|
---|
84 | static QLabel *progressDisplay;
|
---|
85 | static bool *doneSetup;
|
---|
86 | static bool selecting;
|
---|
87 | static int counter;
|
---|
88 | static int depth;
|
---|
89 |
|
---|
90 | protected:
|
---|
91 | virtual void stateChange (bool on) {
|
---|
92 | if (firstChild()) {
|
---|
93 | if (!selecting) {
|
---|
94 | progressDisplay->setText (QString ("%1electing %2...").arg (on? "S" : "Des").arg (_text));
|
---|
95 | counter = depth = 0;
|
---|
96 | selecting = true;
|
---|
97 | if (doneSetup) *doneSetup = false;
|
---|
98 | }
|
---|
99 |
|
---|
100 | for (QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling()) {
|
---|
101 | XMCheckListItem *cli;
|
---|
102 | if ((cli = dynamic_cast <XMCheckListItem *> (lvi)) != 0) {
|
---|
103 | if (!(++counter % 10000)) {
|
---|
104 | progressDisplay->setText (progressDisplay->text() + ".");
|
---|
105 | }
|
---|
106 | if (!(counter % 1000)) {
|
---|
107 | kapp->processEvents();
|
---|
108 | }
|
---|
109 | depth++;
|
---|
110 | cli->setOn (on);
|
---|
111 | depth--;
|
---|
112 | }
|
---|
113 | }
|
---|
114 |
|
---|
115 | if (depth == 0) {
|
---|
116 | selecting = false;
|
---|
117 | progressDisplay->setText ("Please select files and directories to be restored.");
|
---|
118 | if (doneSetup) *doneSetup = true;
|
---|
119 | }
|
---|
120 | }
|
---|
121 | }
|
---|
122 |
|
---|
123 | private:
|
---|
124 | // Ugly hack, but it works: fix segfault
|
---|
125 | QString _text;
|
---|
126 | };
|
---|
127 |
|
---|
128 | QLabel *XMCheckListItem::progressDisplay = 0;
|
---|
129 | bool XMCheckListItem::selecting = false;
|
---|
130 | bool *XMCheckListItem::doneSetup = 0;
|
---|
131 | int XMCheckListItem::counter = 0;
|
---|
132 | int XMCheckListItem::depth = 0;
|
---|
133 |
|
---|
134 | struct XM_node
|
---|
135 | {
|
---|
136 | QString s;
|
---|
137 | XM_node *firstChild;
|
---|
138 | XM_node *nextSibling;
|
---|
139 | };
|
---|
140 |
|
---|
141 | #define XMLF_OK 0
|
---|
142 | #define XMLF_CANTOPEN 1
|
---|
143 |
|
---|
144 | // Requirements:
|
---|
145 | // - File must be sorted
|
---|
146 | // - Entry for a directory must come directly before entries for its files
|
---|
147 | void XM_load_filelist_sub (FILE *fp, QStringList first, XMCheckListItem *top, QLabel *status, int numlines)
|
---|
148 | {
|
---|
149 | static int depth = 0;
|
---|
150 | static int lino = 0;
|
---|
151 | bool tristated = false;
|
---|
152 |
|
---|
153 | char line[4095];
|
---|
154 | while (fgets (line, 4095, fp)) {
|
---|
155 | bool chomped = false;
|
---|
156 |
|
---|
157 | if (line[strlen (line) - 1] == '\n') {
|
---|
158 | line[strlen (line) - 1] = 0;
|
---|
159 | chomped = true;
|
---|
160 | }
|
---|
161 |
|
---|
162 | QStringList dirComponents = QStringList::split ("/", line);
|
---|
163 | if (dirComponents.size() == 0) continue;
|
---|
164 | if (depth > 0) {
|
---|
165 | bool good = true;
|
---|
166 | for (int i = 0; (i < dirComponents.size()) && (i < first.size()) && (i < depth); ++i)
|
---|
167 | if (dirComponents[i] != first[i])
|
---|
168 | good = false;
|
---|
169 | if (!good) {
|
---|
170 | fseek (fp, -(strlen (line) + chomped), SEEK_CUR); // equivalent of "pushback"
|
---|
171 | return;
|
---|
172 | }
|
---|
173 | }
|
---|
174 | XMCheckListItem *newitem = new XMCheckListItem (top, dirComponents[dirComponents.size() - 1]);
|
---|
175 | if (!(++lino % 1111)) {
|
---|
176 | status->setText (QString ("Loading filelist - %1% done").arg (lino * 100 / numlines));
|
---|
177 | }
|
---|
178 |
|
---|
179 | depth++;
|
---|
180 | XM_load_filelist_sub (fp, dirComponents, newitem, status, numlines);
|
---|
181 | depth--;
|
---|
182 | }
|
---|
183 | }
|
---|
184 |
|
---|
185 | int XM_load_filelist (const char *filelist_fname, QListView *list, QLabel *status, QStringList first = QStringList(), FILE *fp = 0)
|
---|
186 | {
|
---|
187 | fp = fopen (filelist_fname, "r");
|
---|
188 | if (!fp) return XMLF_CANTOPEN;
|
---|
189 |
|
---|
190 | XMCheckListItem *top = new XMCheckListItem (list, "/");
|
---|
191 |
|
---|
192 | status->setText ("Loading filelist - 0% done");
|
---|
193 | XM_load_filelist_sub (fp, QStringList(), top, status, atoi (call_program_and_get_last_line_of_output (const_cast <char*> (QString ("wc -l %1").arg (filelist_fname).ascii()))));
|
---|
194 |
|
---|
195 | fclose (fp);
|
---|
196 | return XMLF_OK;
|
---|
197 | }
|
---|
198 |
|
---|
199 | void *XMondoRestore_preparer_thread (void *arg)
|
---|
200 | {
|
---|
201 | XMondoRestore *r = static_cast<XMondoRestore*> (arg);
|
---|
202 | int i = 0;
|
---|
203 | g_current_media_number = 1;
|
---|
204 |
|
---|
205 | r->fStatusMsg->setText ("Retrieving mondo-restore.cfg from archive...");
|
---|
206 |
|
---|
207 | struct s_bkpinfo *bkpinfo = r->bkpinfo;
|
---|
208 | reset_bkpinfo (bkpinfo);
|
---|
209 | switch (r->rMediaType->id (r->rMediaType->selected())) {
|
---|
210 | case 0:
|
---|
211 | bkpinfo->backup_media_type = cdr;
|
---|
212 | break;
|
---|
213 | case 1:
|
---|
214 | bkpinfo->backup_media_type = cdrw;
|
---|
215 | bkpinfo->wipe_media_first = 1;
|
---|
216 | break;
|
---|
217 | case 2:
|
---|
218 | bkpinfo->backup_media_type = cdstream;
|
---|
219 | break;
|
---|
220 | case 3:
|
---|
221 | bkpinfo->backup_media_type = dvd;
|
---|
222 | break;
|
---|
223 | case 4:
|
---|
224 | bkpinfo->backup_media_type = iso;
|
---|
225 | break;
|
---|
226 | case 5:
|
---|
227 | bkpinfo->backup_media_type = nfs;
|
---|
228 | break;
|
---|
229 | case 6:
|
---|
230 | bkpinfo->backup_media_type = tape;
|
---|
231 | break;
|
---|
232 | case 7:
|
---|
233 | bkpinfo->backup_media_type = udev;
|
---|
234 | break;
|
---|
235 | }
|
---|
236 |
|
---|
237 | strcpy (bkpinfo->media_device, r->rDevice->text());
|
---|
238 | if (bkpinfo->backup_media_type == nfs) strcpy (bkpinfo->nfs_mount, r->rDevice->text());
|
---|
239 | if (bkpinfo->backup_media_type == nfs) strcpy (bkpinfo->nfs_remote_dir, r->rNFSRemoteDir->text());
|
---|
240 | if (bkpinfo->backup_media_type == iso) strcpy (bkpinfo->isodir, r->rDevice->text());
|
---|
241 | strcpy (bkpinfo->tmpdir, r->tempdir.ascii());
|
---|
242 |
|
---|
243 | setup_MR_global_filenames (bkpinfo);
|
---|
244 |
|
---|
245 | if (get_cfg_file_from_archive (bkpinfo) != 0) {
|
---|
246 | r->fStatusMsg->setText ("Unable to retrieve mondo-restore.cfg. Please choose another archive source.");
|
---|
247 | r->ok = false;
|
---|
248 | return 0;
|
---|
249 | }
|
---|
250 | read_cfg_file_into_bkpinfo (g_mondo_cfg_file, bkpinfo);
|
---|
251 | if (!does_file_exist (g_mondo_cfg_file)) {
|
---|
252 | r->fStatusMsg->setText ("Unable to retrieve mondo-restore.cfg. Internal error.");
|
---|
253 | r->ok = false;
|
---|
254 | return 0;
|
---|
255 | }
|
---|
256 | if (!does_file_exist (g_filelist_full)) {
|
---|
257 | chdir (bkpinfo->tmpdir);
|
---|
258 | r->fStatusMsg->setText ("Retrieving filelist...");
|
---|
259 | if ((bkpinfo->backup_media_type == tape) || (bkpinfo->backup_media_type == udev) ||
|
---|
260 | (bkpinfo->backup_media_type == cdstream)) {
|
---|
261 | unlink (g_filelist_full);
|
---|
262 | system (QString ("tar -zxf %1 tmp/filelist.full").arg (bkpinfo->media_device).ascii());
|
---|
263 | } else {
|
---|
264 | mount_cdrom (bkpinfo);
|
---|
265 | unlink (g_filelist_full);
|
---|
266 | system ("tar -zxf /mnt/cdrom/images/all.tar.gz tmp/filelist.full");
|
---|
267 | }
|
---|
268 |
|
---|
269 | if (!does_file_exist (g_filelist_full)) {
|
---|
270 | r->fStatusMsg->setText ("Filelist could not be retrieved!");
|
---|
271 | r->ok = false;
|
---|
272 | return 0;
|
---|
273 | }
|
---|
274 | }
|
---|
275 | if (!r->rFilter->text().isEmpty() && !r->rFilter->text().isNull()) {
|
---|
276 | r->fStatusMsg->setText (QString ("Filtering filelist through regexp <tt>%1</tt>...").arg (r->rFilter->text()));
|
---|
277 | if (system (QString ("egrep '%2' %1 > %3.FILT").arg (g_filelist_full).arg (r->rFilter->text()).arg (g_filelist_full).ascii()) != 0) {
|
---|
278 | r->fStatusMsg->setText ("Filter failed, using whole filelist");
|
---|
279 | rename (g_filelist_full, QString ("%1.FILT").arg (g_filelist_full).ascii());
|
---|
280 | usleep (500000);
|
---|
281 | }
|
---|
282 | } else {
|
---|
283 | rename (g_filelist_full, QString ("%1.FILT").arg (g_filelist_full).ascii());
|
---|
284 | }
|
---|
285 |
|
---|
286 | r->fStatusMsg->setText ("Preparing filelist - 0% done");
|
---|
287 |
|
---|
288 | int nlines = atoi (call_program_and_get_last_line_of_output (const_cast<char*> (QString ("wc -l %1.FILT").arg (g_filelist_full).ascii())));
|
---|
289 | int curline = 0;
|
---|
290 | FILE *fin = fopen (QString ("%1.FILT").arg (g_filelist_full).ascii(), "r");
|
---|
291 | FILE *fout = popen (QString ("sort -u > %1").arg (g_filelist_full).ascii(), "w");
|
---|
292 |
|
---|
293 | if (!(fin && fout)) {
|
---|
294 | r->fStatusMsg->setText ("Can't open filelist");
|
---|
295 | r->ok = false;
|
---|
296 | return 0;
|
---|
297 | }
|
---|
298 |
|
---|
299 | char line[4096], tmp[4096];
|
---|
300 | while (fgets (line, 4096, fin)) {
|
---|
301 | if (line[strlen (line) - 1] == '\n')
|
---|
302 | line[strlen (line) - 1] = '\0';
|
---|
303 |
|
---|
304 | for (int pos = 0; line[pos] != '\0'; pos++) {
|
---|
305 | if (line[pos] != '/') continue;
|
---|
306 | strcpy (tmp, line);
|
---|
307 | tmp[pos] = '\0';
|
---|
308 | if (strlen (tmp)) {
|
---|
309 | fprintf (fout, "%s\n", tmp);
|
---|
310 | }
|
---|
311 | }
|
---|
312 | fprintf (fout, "%s\n", line);
|
---|
313 | if (!(++curline % 1111)) {
|
---|
314 | r->fStatusMsg->setText (QString ("Preparing filelist - %1% done").arg (curline * 100 / nlines));
|
---|
315 | }
|
---|
316 | }
|
---|
317 |
|
---|
318 | fclose (fin);
|
---|
319 | pclose (fout);
|
---|
320 |
|
---|
321 | if (XM_load_filelist (g_filelist_full, r->fList, r->fStatusMsg) != XMLF_OK) {
|
---|
322 | r->fStatusMsg->setText ("Error loading filelist");
|
---|
323 | r->ok = false;
|
---|
324 | return 0;
|
---|
325 | }
|
---|
326 | r->fStatusMsg->setText ("Filelist loaded OK");
|
---|
327 |
|
---|
328 | r->doneSetup = true;
|
---|
329 | r->fList->setEnabled (true);
|
---|
330 | r->fRestoreDirLabel->setEnabled (true);
|
---|
331 | r->fRestoreDir->setEnabled (true);
|
---|
332 | sleep (1);
|
---|
333 | r->fStatusMsg->setText ("Please select files and directories to be restored.");
|
---|
334 | XMCheckListItem::progressDisplay = r->fStatusMsg;
|
---|
335 | XMCheckListItem::doneSetup = &(r->doneSetup);
|
---|
336 |
|
---|
337 | return 0;
|
---|
338 | }
|
---|
339 |
|
---|
340 | XMondoRestore::XMondoRestore (QWidget *parent, QButtonGroup *mediaType, QLineEdit *device, QLineEdit *nfsRemoteDir, QLineEdit *filelistFilter)
|
---|
341 | : QObject (0, 0), rMediaType (mediaType), rDevice (device), rNFSRemoteDir (nfsRemoteDir), rFilter (filelistFilter), ok (true), files (parent), doneSetup (false), th (0)
|
---|
342 | {
|
---|
343 | bkpinfo = new s_bkpinfo;
|
---|
344 |
|
---|
345 | char tmp[256];
|
---|
346 | strcpy (tmp, "/tmp/xmondo.rstr.XXXXXX");
|
---|
347 | mktemp (tmp);
|
---|
348 | tempdir = tmp;
|
---|
349 | filelistLocation = tempdir + "/filelist.full";
|
---|
350 | cfgLocation = tempdir + "/mondo-restore.cfg";
|
---|
351 | cdMountpoint = "/mnt/cdrom";
|
---|
352 |
|
---|
353 | if (!does_file_exist ("/mnt/cdrom")) {
|
---|
354 | if (system ("mkdir -p /mnt/cdrom >/dev/null 2>&1") != 0) {
|
---|
355 | popup_and_OK ("Can't create /mnt/cdrom directory. Aborting restore.");
|
---|
356 | ok = false;
|
---|
357 | return;
|
---|
358 | }
|
---|
359 | }
|
---|
360 |
|
---|
361 | QGridLayout *filesGrid;
|
---|
362 | filesGrid = new QGridLayout (files, 3, 2, 5, 5, "filesGrid");
|
---|
363 | fStatusMsg = new QLabel ("", files);
|
---|
364 | fList = new QListView (files);
|
---|
365 | fRestoreDirLabel = new QLabel ("Restore to:", files);
|
---|
366 | fRestoreDir = new QLineEdit (files);
|
---|
367 |
|
---|
368 | fList->addColumn ("Files to restore:");
|
---|
369 | fList->setRootIsDecorated (true);
|
---|
370 | fList->setEnabled (false);
|
---|
371 | fRestoreDirLabel->setEnabled (false);
|
---|
372 | fRestoreDir->setEnabled (false);
|
---|
373 | fRestoreDir->setText ("/tmp");
|
---|
374 | filesGrid->addMultiCellWidget (fStatusMsg, 0, 0, 0, 1);
|
---|
375 | filesGrid->addMultiCellWidget (fList, 1, 1, 0, 1);
|
---|
376 | filesGrid->addWidget (fRestoreDirLabel, 2, 0);
|
---|
377 | filesGrid->addWidget (fRestoreDir, 2, 1);
|
---|
378 |
|
---|
379 | while (system ("mount | grep -q /mnt/cdrom") == 1) {
|
---|
380 | if (QMessageBox::warning (0, "XMondo", QString ("CD is mounted. Please unmount it and try again."), "&Retry", "&Cancel") == 1 /* Cancel */) {
|
---|
381 | ok = false;
|
---|
382 | return;
|
---|
383 | }
|
---|
384 | }
|
---|
385 |
|
---|
386 | pthread_create (&preparer_thread, 0, XMondoRestore_preparer_thread, static_cast <void*> (this));
|
---|
387 | ok = true;
|
---|
388 | }
|
---|
389 |
|
---|
390 | XMondoRestore::~XMondoRestore()
|
---|
391 | {
|
---|
392 | chdir ("/");
|
---|
393 | pthread_cancel (preparer_thread);
|
---|
394 | system (QString ("mount | grep xmondo.rstr | cut -d' ' -f3 | xargs umount"));
|
---|
395 | system (QString ("umount %1/mount.bootdisk >/dev/null 2>&1").arg (tempdir).ascii());
|
---|
396 | if ((tempdir != "") && (tempdir != "/") && (tempdir != "/tmp") && (tempdir != "/tmp/")) {
|
---|
397 | system (QString ("rm -rf %1").arg (tempdir).ascii());
|
---|
398 | }
|
---|
399 | system (QString ("umount %1 >/dev/null 2>&1").arg (cdMountpoint).ascii());
|
---|
400 | delete bkpinfo;
|
---|
401 | }
|
---|
402 |
|
---|
403 | int XM_save_filelist (QListViewItem *liTop, const char *fname, QString prefix = QString (""), int numlines = 0, int curline = 0, FILE *fp = 0)
|
---|
404 | {
|
---|
405 | static int depth = 0;
|
---|
406 |
|
---|
407 | if (!depth) {
|
---|
408 | numlines = atoi (call_program_and_get_last_line_of_output (const_cast<char*> (QString ("wc -l %1").arg (fname).ascii())));
|
---|
409 | fp = fopen (fname, "w");
|
---|
410 | if (!fp) return 1;
|
---|
411 | fprintf (fp, "/\n");
|
---|
412 | if (!liTop) {
|
---|
413 | popup_and_OK ("Internal error. No entries in filelist.");
|
---|
414 | return 255;
|
---|
415 | }
|
---|
416 | }
|
---|
417 |
|
---|
418 | XMCheckListItem *top = dynamic_cast<XMCheckListItem*> (liTop);
|
---|
419 | if (!top) return 2;
|
---|
420 |
|
---|
421 | for (; top; top = dynamic_cast<XMCheckListItem*> (top->nextSibling())) {
|
---|
422 | if (!top) return 2;
|
---|
423 | if (top->isOn()) {
|
---|
424 | fprintf (fp, "%s/%s\n", prefix.ascii(), top->text().ascii());
|
---|
425 | }
|
---|
426 | if (!(++curline % 1000)) {
|
---|
427 | XMondoProgress->setProgress (curline * 100 / numlines);
|
---|
428 | kapp->processEvents();
|
---|
429 | }
|
---|
430 | if (top->firstChild()) {
|
---|
431 | depth++;
|
---|
432 | XM_save_filelist (top->firstChild(), "", prefix + "/" + top->text(), numlines, curline, fp);
|
---|
433 | depth--;
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 | if (!depth) {
|
---|
438 | fclose (fp);
|
---|
439 | }
|
---|
440 | return 0;
|
---|
441 | }
|
---|
442 |
|
---|
443 |
|
---|
444 | void *RestoreThread__run (void *arg);
|
---|
445 |
|
---|
446 | class RestoreThread
|
---|
447 | {
|
---|
448 | friend void *RestoreThread__run (void *arg);
|
---|
449 | public:
|
---|
450 | RestoreThread (struct s_bkpinfo *bkpinfo, struct s_node *filelist) : _bkpinfo (bkpinfo), _filelist (filelist),
|
---|
451 | _ret (-1), _aborted (false) {}
|
---|
452 | int returns() {
|
---|
453 | return _ret;
|
---|
454 | }
|
---|
455 | void start() {
|
---|
456 | _running = true;
|
---|
457 | pthread_create (&_thr, 0, RestoreThread__run, this);
|
---|
458 | }
|
---|
459 | void terminate() {
|
---|
460 | _running = false;
|
---|
461 | pthread_cancel (_thr);
|
---|
462 | _thr = 0;
|
---|
463 | }
|
---|
464 | bool running() {
|
---|
465 | return _running;
|
---|
466 | }
|
---|
467 | bool aborted() {
|
---|
468 | return _aborted;
|
---|
469 | }
|
---|
470 | protected:
|
---|
471 | static void setStop (void *arg) {
|
---|
472 | RestoreThread *rt = static_cast <RestoreThread*> (arg);
|
---|
473 | if (!rt) return;
|
---|
474 | rt->_running = false;
|
---|
475 | rt->_ret = -1;
|
---|
476 | rt->_aborted = true;
|
---|
477 | }
|
---|
478 | void run() {
|
---|
479 | pthread_cleanup_push (RestoreThread::setStop, this);
|
---|
480 |
|
---|
481 | log_to_screen ("Restore started on %s", call_program_and_get_last_line_of_output ("date"));
|
---|
482 | _ret = restore_everything (_bkpinfo, _filelist);
|
---|
483 | log_to_screen ("Restore finished on %s", call_program_and_get_last_line_of_output ("date"));
|
---|
484 | pthread_cleanup_pop (FALSE);
|
---|
485 | _running = false;
|
---|
486 | }
|
---|
487 | struct s_bkpinfo *_bkpinfo;
|
---|
488 | struct s_node *_filelist;
|
---|
489 | int _ret;
|
---|
490 | pthread_t _thr;
|
---|
491 | bool _running;
|
---|
492 | bool _aborted;
|
---|
493 | };
|
---|
494 |
|
---|
495 | void *RestoreThread__run (void *arg)
|
---|
496 | {
|
---|
497 | RestoreThread *rt = static_cast <RestoreThread *> (arg);
|
---|
498 | if (!rt && (sizeof(void*) >= 4)) return (void *) 0xDEADBEEF;
|
---|
499 | rt->run();
|
---|
500 | }
|
---|
501 |
|
---|
502 | void XMondoRestore::slotAbortRestore()
|
---|
503 | {
|
---|
504 | if (th) th->terminate();
|
---|
505 | }
|
---|
506 |
|
---|
507 | void XM_toggle_everything_on (struct s_node *flist)
|
---|
508 | {
|
---|
509 | for (; flist; flist = flist->right) {
|
---|
510 | if (flist->ch == 0) {
|
---|
511 | flist->selected = 1;
|
---|
512 | }
|
---|
513 | if (flist->down) {
|
---|
514 | XM_toggle_everything_on (flist->down);
|
---|
515 | }
|
---|
516 | }
|
---|
517 | }
|
---|
518 |
|
---|
519 | void XMondoRestore::go()
|
---|
520 | {
|
---|
521 | if (!doneSetup) {
|
---|
522 | popup_and_OK ("Please wait for the setup to be completed.");
|
---|
523 | ok = false;
|
---|
524 | return;
|
---|
525 | }
|
---|
526 | pthread_cancel (preparer_thread);
|
---|
527 |
|
---|
528 |
|
---|
529 | disconnect (XMondoCancel, SIGNAL(clicked()), 0, 0);
|
---|
530 | connect (XMondoCancel, SIGNAL(clicked()), this, SLOT(slotAbortRestore()));
|
---|
531 |
|
---|
532 | XMondoProgress->show();
|
---|
533 | XMondoProgress->setTotalSteps (100);
|
---|
534 | XMondoProgress->setProgress (0);
|
---|
535 | XMondoProgressWhat->show();
|
---|
536 | XMondoProgressWhat->setText ("Saving your filelist choices.");
|
---|
537 | XMondoProgressWhat2->hide();
|
---|
538 | XMondoProgressWhat3->hide();
|
---|
539 | XMondoTimeTaken->hide();
|
---|
540 | XMondoTimeToGo->hide();
|
---|
541 | XMondoStatus->setText ("Saving filelist");
|
---|
542 | XMondoStatus->show();
|
---|
543 | XMondoLog->setText ("");
|
---|
544 | XMondoLog->show();
|
---|
545 |
|
---|
546 | if (XM_save_filelist (fList->firstChild()->firstChild(), g_filelist_full) != 0) {
|
---|
547 | XMondoStatus->setText ("Error saving filelist");
|
---|
548 | ok = false;
|
---|
549 | return;
|
---|
550 | }
|
---|
551 |
|
---|
552 | XMondoStatus->setText ("Reloading filelist");
|
---|
553 | /*DEBUG*/ system (QString ("cp %1 /home/oremanj/filelist.tested").arg (g_filelist_full).ascii());
|
---|
554 | s_node *flist = load_filelist (g_filelist_full);
|
---|
555 | if (!flist) {
|
---|
556 | XMondoStatus->setText ("Error loading filelist");
|
---|
557 | ok = false;
|
---|
558 | return;
|
---|
559 | }
|
---|
560 | XM_toggle_everything_on (flist);
|
---|
561 |
|
---|
562 | XMondoProgress->hide();
|
---|
563 | XMondoStatus->setText ("Beginning restore");
|
---|
564 | XMondoProgressWhat->hide();
|
---|
565 |
|
---|
566 | strcpy (bkpinfo->restore_path, fRestoreDir->text().ascii());
|
---|
567 |
|
---|
568 | g_text_mode = 1; // avoid crashing on NEWT functions
|
---|
569 |
|
---|
570 | th = new RestoreThread (bkpinfo, flist);
|
---|
571 | th->start();
|
---|
572 | while (th->running()) {
|
---|
573 | usleep (100000);
|
---|
574 | events.send();
|
---|
575 | kapp->processEvents();
|
---|
576 | }
|
---|
577 | free_filelist (flist);
|
---|
578 | if (th->aborted()) {
|
---|
579 | /* do nothing */
|
---|
580 | } else if (th->returns() == 0) {
|
---|
581 | popup_and_OK ("Restore completed with no errors.");
|
---|
582 | } else {
|
---|
583 | popup_and_OK ("Restore completed; however, there were some errors.");
|
---|
584 | }
|
---|
585 | delete th; th = 0;
|
---|
586 | ok = true; // call destructor in caller
|
---|
587 | }
|
---|