source: branches/stable/mondo/src/mondorestore/mondorestore.c @ 1213

Last change on this file since 1213 was 1213, checked in by Bruno Cornec, 13 years ago

Removal of g_mondo_home useless and used MONDO_SHARE instead

  • Property svn:keywords set to Id
File size: 96.8 KB
Line 
1/***************************************************************************
2* restores mondoarchive data
3* $Id: mondorestore.c 1213 2007-02-26 13:04:43Z bruno $
4***************************************************************************/
5
6/**
7 * @file
8 * The main file for mondorestore.
9 */
10
11/**************************************************************************
12 * #include statements                                                    *
13 **************************************************************************/
14#include <unistd.h>
15#include <utime.h>
16
17#include "my-stuff.h"
18#include "mr_mem.h"
19#include "mr_msg.h"
20#include "mr_str.h"
21
22#include "mondostructures.h"
23#include "libmondo.h"
24#include "mr-externs.h"
25#include "mondo-restore.h"
26#include "mondo-rstr-compare-EXT.h"
27#include "mondo-rstr-tools-EXT.h"
28
29extern void twenty_seconds_til_yikes(void);
30
31
32/* For use in other programs (ex. XMondo) */
33#ifdef MONDORESTORE_MODULE
34#define main __mondorestore_main
35#define g_ISO_restore_mode __mondorestore_g_ISO_restore_mode
36#endif
37
38//static char cvsid[] = "$Id: mondorestore.c 1213 2007-02-26 13:04:43Z bruno $";
39
40/**************************************************************************
41 * Globals                                                                *
42 **************************************************************************/
43extern char *g_tmpfs_mountpt;   // declared in libmondo-tools.c
44extern bool g_text_mode;
45extern FILE *g_fprep;
46extern double g_kernel_version;
47extern int g_partition_table_locked_up;
48extern int g_noof_rows;
49
50extern int partition_everything(struct mountlist_itself *mountlist);
51
52
53/**
54 * @name Restore-Time Globals
55 * @ingroup globalGroup
56 * @{
57 */
58/**
59 * If TRUE, then SIGPIPE was just caught.
60 * Set by the signal handler; cleared after it's handled.
61 */
62bool g_sigpipe_caught = FALSE;
63
64/**
65 * If TRUE, then we're restoring from ISOs or an NFS server.
66 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
67 */
68bool g_ISO_restore_mode = FALSE;    /* are we in Iso Mode? */
69
70/**
71 * If TRUE, then we have had a successful "nuke" restore.
72 */
73bool g_I_have_just_nuked = FALSE;
74
75/**
76 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
77 */
78char *g_isodir_device = NULL;
79
80/**
81 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
82 */
83char *g_isodir_format = NULL;
84
85/**
86 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
87 */
88char *g_biggielist_txt = NULL;
89
90/**
91 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
92 * the current archive set.
93 */
94char *g_filelist_full = NULL;
95
96/**
97 * The location of a file containing a list of the devices that were archived
98 * as images, not as individual files.
99 */
100char *g_filelist_imagedevs = NULL;
101
102/**
103 * The location of a file containing a list of imagedevs to actually restore.
104 * @see g_filelist_imagedevs
105 */
106char *g_imagedevs_restthese = NULL;
107
108/**
109 * The location of 'mondo-restore.cfg', containing the metadata
110 * information for this backup.
111 */
112char *g_mondo_cfg_file = NULL;
113
114/**
115 * The location of 'mountlist.txt', containing the information on the
116 * user's partitions and hard drives.
117 */
118char *g_mountlist_fname = NULL;
119
120/* Busybox ps has no option and PID in first pos */
121char *ps_options = "";
122char *ps_proc_id = "$1";
123
124extern char *g_getfacl;
125extern char *g_getfattr;
126
127/* @} - end of "Restore-Time Globals" in globalGroup */
128
129extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
130                                 char direction);
131
132/**************************************************************************
133 * COMPAQ PROLIANT Stuff:  needs some special help                        *
134**************************************************************************/
135
136/**
137 * The message to display if we detect that the user is using a Compaq Proliant.
138 */
139#define COMPAQ_PROLIANTS_SUCK _("Partition and format your disk using Compaq's disaster recovery CD. After you've done that, please reboot with your Mondo CD/floppy in Interactive Mode.")
140
141
142/**
143 * Allow the user to modify the mountlist before we partition & format their drives.
144 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
145 * @param mountlist The mountlist to let the user modify.
146 * @param raidlist The raidlist that goes with @p mountlist.
147 * @return 0 for success, nonzero for failure.
148 * @ingroup restoreGuiGroup
149 */
150int let_user_edit_the_mountlist(struct s_bkpinfo *bkpinfo,
151                                struct mountlist_itself *mountlist,
152                                struct raidlist_itself *raidlist)
153{
154    int retval = 0, res = 0;
155
156    mr_msg(2, "let_user_edit_the_mountlist() --- starting");
157
158    assert(bkpinfo != NULL);
159    assert(mountlist != NULL);
160    assert(raidlist != NULL);
161    if (!bkpinfo->disaster_recovery) {
162        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
163        mr_msg(2, "I guess you're testing edit_mountlist()");
164    }
165    if (!does_file_exist(g_mountlist_fname)) {
166        log_to_screen(g_mountlist_fname);
167        log_to_screen(_("does not exist"));
168        return (1);
169    }
170
171    retval = load_mountlist(mountlist, g_mountlist_fname);
172    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
173    if (retval) {
174        log_to_screen
175            (_("Warning - load_raidtab_into_raidlist returned an error"));
176    }
177    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
178    if (res) {
179        return (1);
180    }
181
182    save_mountlist_to_disk(mountlist, g_mountlist_fname);
183    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
184
185    log_to_screen(_("I have finished editing the mountlist for you."));
186
187    return (retval);
188}
189
190
191/**
192 * Determine whether @p mountlist contains a Compaq diagnostic partition.
193 * @param mountlist The mountlist to examine.
194 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
195 * @ingroup restoreUtilityGroup
196 */
197bool
198partition_table_contains_Compaq_diagnostic_partition(struct
199                                                     mountlist_itself *
200                                                     mountlist)
201{
202    int i;
203
204    assert(mountlist != NULL);
205
206    for (i = 0; i < mountlist->entries; i++) {
207        if (strstr(mountlist->el[i].format, "ompaq")) {
208            mr_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
209                    i, mountlist->el[i].device, mountlist->el[i].format);
210
211            return (TRUE);
212        }
213    }
214    return (FALSE);
215}
216
217/**************************************************************************
218 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION                *
219 **************************************************************************/
220
221
222/**
223 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
224 * @note This function does not actually check for the presence of a Compaq partition.
225 * @ingroup restoreUtilityGroup
226 */
227void offer_to_abort_because_Compaq_Proliants_suck(void)
228{
229    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
230    if (ask_me_yes_or_no
231        (_("Would you like to reboot and use your Compaq CD to prep your hard drive?")))
232    {
233        fatal_error(_("Aborting. Please reboot and prep your hard drive with your Compaq CD."));
234    }
235}
236
237/**************************************************************************
238 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK                        *
239 **************************************************************************/
240
241
242/**
243 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
244 * @param bkpinfo The backup information structure. Most fields are used.
245 * @param mountlist The mountlist containing information about the user's partitions.
246 * @param raidlist The raidlist to go with @p mountlist.
247 * @return The return code from the mode function called.
248 * @ingroup restoreGroup
249 */
250int
251catchall_mode(struct s_bkpinfo *bkpinfo,
252              struct mountlist_itself *mountlist,
253              struct raidlist_itself *raidlist)
254{
255    char c, *tmp;
256    int retval = 0;
257
258    iamhere("inside catchall");
259    assert(bkpinfo != NULL);
260    assert(mountlist != NULL);
261    assert(raidlist != NULL);
262    iamhere("pre wrm");
263    c = which_restore_mode();
264    iamhere("post wrm");
265    if (c == 'I' || c == 'N' || c == 'C') {
266        interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
267    } else {
268        popup_and_OK(_("No restoring or comparing will take place today."));
269        if (is_this_device_mounted("/mnt/cdrom")) {
270            run_program_and_log_output("umount /mnt/cdrom", FALSE);
271        }
272        if (g_ISO_restore_mode) {
273            mr_asprintf(&tmp, "umount %s", bkpinfo->isodir);
274            run_program_and_log_output(tmp, FALSE);
275            mr_free(tmp);
276        }
277        paranoid_MR_finish(0);
278    }
279
280    iamhere("post int");
281
282    if (bkpinfo->backup_media_type == iso) {
283        if (iso_fiddly_bits(bkpinfo, (c == 'N') ? TRUE : FALSE)) {
284            mr_msg(2,
285                    "catchall_mode --- iso_fiddly_bits returned w/ error");
286            return (1);
287        } else {
288            mr_msg(2, "catchall_mode --- iso_fiddly_bits ok");
289        }
290    }
291
292    if (c == 'I') {
293        mr_msg(2, "IM selected");
294        retval += interactive_mode(bkpinfo, mountlist, raidlist);
295    } else if (c == 'N') {
296        mr_msg(2, "NM selected");
297        retval += nuke_mode(bkpinfo, mountlist, raidlist);
298    } else if (c == 'C') {
299        mr_msg(2, "CM selected");
300        retval += compare_mode(bkpinfo, mountlist, raidlist);
301    }
302    return (retval);
303}
304
305/**************************************************************************
306 *END_CATCHALL_MODE                                                      *
307 **************************************************************************/
308
309/**************************************************************************
310 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
311 **************************************************************************/
312
313
314/**
315 * @addtogroup restoreGroup
316 * @{
317 */
318/**
319 * Restore the user's data, in a disaster recovery situation, prompting the
320 * user about whether or not to do every step.
321 * The user can edit the mountlist, choose files to restore, etc.
322 * @param bkpinfo The backup information structure. Most fields are used.
323 * @param mountlist The mountlist containing information about the user's partitions.
324 * @param raidlist The raidlist to go with @p mountlist.
325 * @return 0 for success, or the number of errors encountered.
326 */
327int
328interactive_mode(struct s_bkpinfo *bkpinfo,
329                 struct mountlist_itself *mountlist,
330                 struct raidlist_itself *raidlist)
331{
332    int retval = 0;
333    int res;
334    int ptn_errs = 0;
335    int fmt_errs = 0;
336
337    bool done;
338    bool restore_all;
339
340    char *tmp = NULL;
341    char *tmp1 = NULL;
342    char *fstab_fname = NULL;
343    char *old_restpath = NULL;
344
345    struct s_node *filelist = NULL;
346
347    /* try to partition and format */
348
349    mr_msg(2, "interactive_mode --- starting (great, assertions OK)");
350
351    assert(bkpinfo != NULL);
352    assert(mountlist != NULL);
353    assert(raidlist != NULL);
354
355    mr_msg(2, "interactive_mode --- assertions OK");
356
357    if (g_text_mode) {
358        if (!ask_me_yes_or_no
359            (_("Interactive Mode + textonly = experimental! Proceed anyway?")))
360        {
361            fatal_error("Wise move.");
362        }
363    }
364
365    iamhere("About to load config file");
366    get_cfg_file_from_archive_or_bust(bkpinfo);
367    read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
368    iamhere("Done loading config file; resizing ML");
369#ifdef __FreeBSD__
370    if (strstr
371        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
372         "noresize"))
373#else
374    if (strstr
375        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
376         "noresize"))
377#endif
378    {
379        mr_msg(1, "Not resizing mountlist.");
380    } else {
381        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
382    }
383    for (done = FALSE; !done;) {
384        iamhere("About to edit mountlist");
385        if (g_text_mode) {
386            save_mountlist_to_disk(mountlist, g_mountlist_fname);
387            mr_asprintf(&tmp, "%s %s", find_my_editor(), g_mountlist_fname);
388            res = system(tmp);
389            mr_free(tmp);
390            load_mountlist(mountlist, g_mountlist_fname);
391        } else {
392            res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
393        }
394        iamhere("Finished editing mountlist");
395        if (res) {
396            paranoid_MR_finish(1);
397        }
398        mr_msg(2, "Proceeding...");
399        save_mountlist_to_disk(mountlist, g_mountlist_fname);
400        save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
401        mvaddstr_and_log_it(1, 30, _("Restoring Interactively"));
402        if (bkpinfo->differential) {
403            log_to_screen(_("Because this is a differential backup, disk"));
404            log_to_screen(_(" partitioning and formatting will not take place."));
405            done = TRUE;
406        } else {
407            if (ask_me_yes_or_no
408                (_("Do you want to erase and partition your hard drives?")))
409            {
410                if (partition_table_contains_Compaq_diagnostic_partition
411                    (mountlist)) {
412                    offer_to_abort_because_Compaq_Proliants_suck();
413                    done = TRUE;
414                } else {
415                    twenty_seconds_til_yikes();
416                    g_fprep = fopen("/tmp/prep.sh", "w");
417                    ptn_errs = partition_everything(mountlist);
418                    if (ptn_errs) {
419                        log_to_screen
420                            (_("Warning. Errors occurred during disk partitioning."));
421                    }
422
423                    fmt_errs = format_everything(mountlist, FALSE, raidlist);
424                    if (!fmt_errs) {
425                        log_to_screen
426                            (_("Errors during disk partitioning were handled OK."));
427                        log_to_screen(_("Partitions were formatted OK despite those errors."));
428                        ptn_errs = 0;
429                    }
430                    if (!ptn_errs && !fmt_errs) {
431                        done = TRUE;
432                    }
433                }
434                paranoid_fclose(g_fprep);
435            } else {
436                mvaddstr_and_log_it(g_currentY++, 0,
437                                    _("User opted not to partition the devices"));
438                if (ask_me_yes_or_no
439                    (_("Do you want to format your hard drives?"))) {
440                    fmt_errs =
441                        format_everything(mountlist, TRUE, raidlist);
442                    if (!fmt_errs) {
443                        done = TRUE;
444                    }
445                } else {
446                    ptn_errs = fmt_errs = 0;
447                    done = TRUE;
448                }
449            }
450            if (fmt_errs) {
451                mvaddstr_and_log_it(g_currentY++,
452                                    0,
453                                    _("Errors occurred. Please repartition and format drives manually."));
454                done = FALSE;
455            }
456            if (ptn_errs & !fmt_errs) {
457                mvaddstr_and_log_it(g_currentY++,
458                                    0,
459                                    _("Errors occurred during partitioning. Formatting, however, went OK."));
460                done = TRUE;
461            }
462            if (!done) {
463                if (!ask_me_yes_or_no(_("Re-edit the mountlist?"))) {
464                    retval++;
465                    iamhere("Leaving interactive_mode()");
466                    return (retval);
467                }
468            }
469        }
470    }
471
472    /* mount */
473    if (mount_all_devices(mountlist, TRUE)) {
474        unmount_all_devices(mountlist);
475        retval++;
476        iamhere("Leaving interactive_mode()");
477        return (retval);
478    }
479    /* restore */
480    if ((restore_all =
481         ask_me_yes_or_no(_("Do you want me to restore all of your data?"))))
482    {
483        mr_msg(1, "Restoring all data");
484        retval += restore_everything(bkpinfo, NULL);
485    } else if ((restore_all =
486             ask_me_yes_or_no
487             (_("Do you want me to restore _some_ of your data?")))) {
488        mr_asprintf(&old_restpath,bkpinfo->restore_path);
489        for (done = FALSE; !done;) {
490            unlink("/tmp/filelist.full");
491            filelist = process_filelist_and_biggielist(bkpinfo);
492            /* Now you have /tmp/tmpfs/filelist.restore-these and /tmp/tmpfs/biggielist.restore-these;
493               the former is a list of regular files; the latter, biggiefiles and imagedevs.
494             */
495            if (filelist) {
496                malloc_string(tmp1);
497              gotos_suck:
498                strcpy(tmp1, old_restpath);
499                // (NB: MNT_RESTORING is where your filesystem is mounted now, by default)
500                if (popup_and_get_string
501                    (_("Restore path"), _("Restore files to where?"), tmp1,
502                     MAX_STR_LEN / 4)) {
503                    if (!strcmp(tmp1, "/")) {
504                        if (!ask_me_yes_or_no(_("Are you sure?"))) {
505                            goto gotos_suck;
506                        }
507                        tmp1[0] = '\0'; // so we restore to [blank]/file/name :)
508                    }
509                    strcpy(bkpinfo->restore_path, tmp1);
510                    mr_msg(1, "Restoring subset");
511                    retval += restore_everything(bkpinfo, filelist);
512                    free_filelist(filelist);
513                } else {
514                    strcpy(bkpinfo->restore_path, old_restpath);
515                    free_filelist(filelist);
516                }
517                if (!ask_me_yes_or_no
518                    (_("Restore another subset of your backup?"))) {
519                    done = TRUE;
520                }
521                mr_free(tmp1);
522            } else {
523                done = TRUE;
524            }
525        }
526        mr_free(old_restpath);
527    } else {
528        mvaddstr_and_log_it(g_currentY++,
529                            0,
530                            _("User opted not to restore any data.                                  "));
531    }
532    if (retval) {
533        mvaddstr_and_log_it(g_currentY++,
534                            0,
535                            _("Errors occurred during the restore phase.            "));
536    }
537
538    if (ask_me_yes_or_no(_("Initialize the boot loader?"))) {
539        run_boot_loader(TRUE);
540    } else {
541        mvaddstr_and_log_it(g_currentY++,
542                            0,
543                            _("User opted not to initialize the boot loader."));
544    }
545
546    protect_against_braindead_sysadmins();
547    retval += unmount_all_devices(mountlist);
548    /*  if (restore_some || restore_all || */
549    if (ask_me_yes_or_no
550        (_("Label your ext2 and ext3 partitions if necessary?"))) {
551        mvaddstr_and_log_it(g_currentY, 0,
552                            _("Using e2label to label your ext2,3 partitions"));
553        if (does_file_exist("/tmp/fstab.new")) {
554            mr_asprintf(&fstab_fname, "/tmp/fstab.new");
555        } else {
556            mr_asprintf(&fstab_fname, "/tmp/fstab");
557        }
558        mr_asprintf(&tmp,
559                "label-partitions-as-necessary %s < %s >> %s 2>> %s",
560                g_mountlist_fname, fstab_fname, MONDO_LOGFILE,
561                MONDO_LOGFILE);
562        mr_free(fstab_fname);
563
564        res = system(tmp);
565        mr_free(tmp);
566        if (res) {
567            log_to_screen
568                (_("label-partitions-as-necessary returned an error"));
569            mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
570        } else {
571            mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
572        }
573        retval += res;
574    }
575
576    iamhere("About to leave interactive_mode()");
577    if (retval) {
578        mvaddstr_and_log_it(g_currentY++,
579                            0,
580                            _("Warning - errors occurred during the restore phase."));
581    }
582    iamhere("Leaving interactive_mode()");
583    return(retval);
584}
585
586/**************************************************************************
587 *END_INTERACTIVE_MODE                                                    *
588 **************************************************************************/
589
590
591/**
592 * Run an arbitrary restore mode (prompt the user), but from ISO images
593 * instead of real media.
594 * @param bkpinfo The backup information structure. Most fields are used.
595 * @param mountlist The mountlist containing information about the user's partitions.
596 * @param raidlist The raidlist that goes with @p mountlist.
597 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
598 * @return 0 for success, or the number of errors encountered.
599 */
600int
601iso_mode(struct s_bkpinfo *bkpinfo,
602         struct mountlist_itself *mountlist,
603         struct raidlist_itself *raidlist, bool nuke_me_please)
604{
605    char c = ' ';
606    int retval = 0;
607
608    assert(bkpinfo != NULL);
609    assert(mountlist != NULL);
610    assert(raidlist != NULL);
611    if (iso_fiddly_bits(bkpinfo, nuke_me_please)) {
612        mr_msg(1, "iso_mode --- returning w/ error");
613        return (1);
614    } else {
615        c = which_restore_mode();
616        if (c == 'I' || c == 'N' || c == 'C') {
617            interactively_obtain_media_parameters_from_user(bkpinfo,
618                                                            FALSE);
619        }
620        if (c == 'I') {
621            retval += interactive_mode(bkpinfo, mountlist, raidlist);
622        } else if (c == 'N') {
623            retval += nuke_mode(bkpinfo, mountlist, raidlist);
624        } else if (c == 'C') {
625            retval += compare_mode(bkpinfo, mountlist, raidlist);
626        } else {
627            log_to_screen(_("OK, I shan't restore/compare any files."));
628        }
629    }
630    if (is_this_device_mounted(MNT_CDROM)) {
631        paranoid_system("umount " MNT_CDROM);
632    }
633    if (system("umount /tmp/isodir 2> /dev/null")) {
634        log_to_screen
635            (_("WARNING - unable to unmount device where the ISO files are stored."));
636    }
637    return (retval);
638}
639
640/**************************************************************************
641 *END_ISO_MODE                                                            *
642 **************************************************************************/
643static void call_me_after_the_nuke(int retval) {
644
645    char *tmp = NULL;
646    char *tmp1 = NULL;
647
648    if (retval) {
649        log_to_screen(_("Errors occurred during the nuke phase."));
650        log_to_screen(_("Please visit our website at http://www.mondorescue.org for more information."));
651    } else {
652#ifdef __FreeBSD__
653    tmp1 = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
654#else
655    tmp1 = call_program_and_get_last_line_of_output("cat /proc/cmdline");
656#endif
657        if ((strstr(tmp1,"restore") == NULL) ||
658            (strstr(tmp1,"RESTORE") == NULL)) {
659            /* -H option */
660            mr_asprintf(&tmp,
661                _(" Mondo has restored your system. Please remove the backup media and reboot.\n\nPlease visit our website at http://www.mondorescue.org for more information."));
662            popup_and_OK(tmp);
663            mr_free(tmp);
664        }
665
666        log_to_screen(_("Mondo has restored your system. Please remove the backup media and reboot."));
667        log_to_screen(_("Thank you for using Mondo Rescue."));
668        log_to_screen(_("Please visit our website at http://www.mondorescue.org for more information."));
669    }
670    g_I_have_just_nuked = TRUE;
671    return;
672}
673
674
675/**
676 * Restore the user's data automatically (no prompts), after a twenty-second
677 * warning period.
678 * @param bkpinfo The backup information structure. Most fields are used.
679 * @param mountlist The mountlist containing information about the user's partitions.
680 * @param raidlist The raidlist that goes with @p mountlist.
681 * @return 0 for success, or the number of errors encountered.
682 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
683 */
684int
685nuke_mode(struct s_bkpinfo *bkpinfo,
686          struct mountlist_itself *mountlist,
687          struct raidlist_itself *raidlist)
688{
689    int retval = 0;
690    int res = 0;
691    bool boot_loader_installed = FALSE;
692    char *tmp = NULL;
693    char tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
694        tmpC[MAX_STR_LEN];
695
696    assert(bkpinfo != NULL);
697    assert(mountlist != NULL);
698    assert(raidlist != NULL);
699
700    mr_msg(2, "nuke_mode --- starting");
701
702    get_cfg_file_from_archive_or_bust(bkpinfo);
703    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo updated the mountlist
704#ifdef __FreeBSD__
705    tmp = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
706#else
707    tmp = call_program_and_get_last_line_of_output("cat /proc/cmdline");
708#endif
709    if (strstr(tmp,"noresize")) {
710        mr_msg(2, "Not resizing mountlist.");
711    } else {
712        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
713    }
714    if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
715        mr_asprintf(&tmp,
716                _("Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?"),
717                tmpA, tmpB, tmpC);
718        if (ask_me_yes_or_no(tmp)) {
719            mr_free(tmp);
720            retval = interactive_mode(bkpinfo, mountlist, raidlist);
721            call_me_after_the_nuke(retval);
722            return(retval);
723        } else {
724            mr_free(tmp);
725            fatal_error("Nuke Mode aborted. ");
726        }
727    }
728    save_mountlist_to_disk(mountlist, g_mountlist_fname);
729    mvaddstr_and_log_it(1, 30, _("Restoring Automatically"));
730    if (bkpinfo->differential) {
731        log_to_screen(_("Because this is a differential backup, disk"));
732        log_to_screen(_("partitioning and formatting will not take place."));
733        res = 0;
734    } else {
735        if (partition_table_contains_Compaq_diagnostic_partition
736            (mountlist)) {
737            offer_to_abort_because_Compaq_Proliants_suck();
738        } else {
739            twenty_seconds_til_yikes();
740            g_fprep = fopen("/tmp/prep.sh", "w");
741#ifdef __FreeBSD__
742            tmp = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
743#else
744            tmp = call_program_and_get_last_line_of_output("cat /proc/cmdline");
745#endif
746            if (strstr(tmp,"nopart")) {
747                mr_msg(2,
748                        "Not partitioning drives due to 'nopart' option.");
749                res = 0;
750            } else {
751                res = partition_everything(mountlist);
752                if (res) {
753                    log_to_screen
754                        (_("Warning. Errors occurred during partitioning."));
755                    res = 0;
756                }
757            }
758            retval += res;
759            if (!res) {
760                log_to_screen(_("Preparing to format your disk(s)"));
761                sleep(1);
762                sync();
763                log_to_screen(_("Please wait. This may take a few minutes."));
764                res += format_everything(mountlist, FALSE, raidlist);
765            }
766            paranoid_fclose(g_fprep);
767        }
768    }
769    retval += res;
770    if (res) {
771        mvaddstr_and_log_it(g_currentY++,
772                            0,
773                            _("Failed to partition and/or format your hard drives."));
774
775        if (ask_me_yes_or_no(_("Try in interactive mode instead?"))) {
776            retval = interactive_mode(bkpinfo, mountlist, raidlist);
777            call_me_after_the_nuke(retval);
778            return(retval);
779        } else
780            if (!ask_me_yes_or_no
781                (_("Would you like to try to proceed anyway?"))) {
782                return(retval);
783        }
784    }
785    retval = mount_all_devices(mountlist, TRUE);
786    if (retval) {
787        unmount_all_devices(mountlist);
788        log_to_screen
789            (_("Unable to mount all partitions. Sorry, I cannot proceed."));
790        return (retval);
791    }
792    iamhere("Restoring everything");
793    retval += restore_everything(bkpinfo, NULL);
794    if (!run_boot_loader(FALSE)) {
795        mr_msg(1,
796                "Great! Boot loader was installed. No need for msg at end.");
797        boot_loader_installed = TRUE;
798    }
799    protect_against_braindead_sysadmins();
800    retval += unmount_all_devices(mountlist);
801    mvaddstr_and_log_it(g_currentY,
802                        0,
803                        _("Using e2label to label your ext2,3 partitions"));
804
805    mr_asprintf(&tmp, "label-partitions-as-necessary %s < /tmp/fstab",
806            g_mountlist_fname);
807    res = run_program_and_log_output(tmp, TRUE);
808    mr_free(tmp);
809
810    if (res) {
811        log_to_screen(_("label-partitions-as-necessary returned an error"));
812        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
813    } else {
814        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
815    }
816    retval += res;
817
818    call_me_after_the_nuke(retval);
819    return (retval);
820}
821
822/**************************************************************************
823 *END_NUKE_MODE                                                           *
824 **************************************************************************/
825
826
827/**
828 * Restore the user's data (or a subset of it) to the live filesystem.
829 * This should not be called if we're booted from CD!
830 * @param bkpinfo The backup information structure. Most fields are used.
831 * @return 0 for success, or the number of errors encountered.
832 */
833int restore_to_live_filesystem(struct s_bkpinfo *bkpinfo)
834{
835    int retval = 0;
836
837    char *old_restpath = NULL;
838
839    struct mountlist_itself *mountlist = NULL;
840    struct raidlist_itself *raidlist = NULL;
841    struct s_node *filelist = NULL;
842
843    mr_msg(1, "restore_to_live_filesystem() - starting");
844    assert(bkpinfo != NULL);
845
846    mountlist = mr_malloc(sizeof(struct mountlist_itself));
847    raidlist = mr_malloc(sizeof(struct raidlist_itself));
848
849    strcpy(bkpinfo->restore_path, "/");
850    if (!g_restoring_live_from_cd) {
851        popup_and_OK
852            (_("Please insert tape/CD/boot floppy, then hit 'OK' to continue."));
853        sleep(1);
854    }
855    interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
856    if (!bkpinfo->media_device[0]) {
857        mr_msg(2, "Warning - failed to find media dev");
858    } else {
859        mr_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
860    }
861
862
863    mr_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
864
865    open_evalcall_form(_("Thinking..."));
866
867    get_cfg_file_from_archive_or_bust(bkpinfo);
868    read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
869    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
870
871    close_evalcall_form();
872    retval = load_mountlist(mountlist, g_mountlist_fname);
873    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
874    filelist = process_filelist_and_biggielist(bkpinfo);
875    if (filelist) {
876        save_filelist(filelist, "/tmp/selected-files.txt");
877        mr_asprintf(&old_restpath,bkpinfo->restore_path);
878        if (popup_and_get_string(_("Restore path"),
879                                 _("Restore files to where? "),
880                                 bkpinfo->restore_path, MAX_STR_LEN)) {
881            iamhere("Restoring everything");
882            retval += restore_everything(bkpinfo, filelist);
883        }
884        free_filelist(filelist);
885        strcpy(bkpinfo->restore_path, old_restpath);
886        mr_free(old_restpath);
887    }
888    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
889        mr_msg(2,
890                "I probably don't need to unmount or eject the CD-ROM but I'm doing it anyway.");
891    }
892    run_program_and_log_output("umount " MNT_CDROM, FALSE);
893    if ((!bkpinfo->please_dont_eject) && (bkpinfo->media_device != NULL)) {
894        eject_device(bkpinfo->media_device);
895    }
896    mr_free(mountlist);
897    mr_free(raidlist);
898    return (retval);
899}
900
901/**************************************************************************
902 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
903 **************************************************************************/
904
905/* @} - end of restoreGroup */
906
907
908/**
909 * @addtogroup LLrestoreGroup
910 * @{
911 */
912/**
913 * Restore biggiefile @p bigfileno from the currently mounted CD.
914 * @param bkpinfo The backup information structure. Fields used:
915 * - @c bkpinfo->backup_media_type
916 * - @c bkpinfo->restore_path
917 * @param bigfileno The biggiefile number (starting from 0) to restore.
918 * @param filelist The node structure containing the list of files to restore.
919 * If the biggiefile is not in this list, it will be skipped (return value will
920 * still indicate success).
921 * @return 0 for success (or skip), nonzero for failure.
922 */
923int
924restore_a_biggiefile_from_CD(struct s_bkpinfo *bkpinfo,
925                             long bigfileno,
926                             struct s_node *filelist,
927                             char *pathname_of_last_file_restored)
928{
929    FILE *fin = NULL;
930    FILE *fout = NULL;
931    FILE *fbzip2 = NULL;
932
933    char *checksum = NULL;
934    char *outfile_fname = NULL;
935    char *tmp = NULL;
936    char *bzip2_command = NULL;
937    char *suffix = NULL;
938    char *bigblk = NULL;
939    int retval = 0;
940    int finished = FALSE;
941    long sliceno = 0L;
942    long siz;
943    char *ntfsprog_fifo = NULL;
944    char *file_to_openout = NULL;
945    struct s_filename_and_lstat_info biggiestruct;
946    struct utimbuf the_utime_buf, *ubuf = NULL;
947    bool use_ntfsprog_hack = FALSE;
948    pid_t pid;
949    int res = 0;
950    int old_loglevel;
951    char *sz_msg = NULL;
952    struct s_node *node = NULL;
953
954    old_loglevel = g_loglevel;
955    ubuf = &the_utime_buf;
956    assert(bkpinfo != NULL);
957
958    pathname_of_last_file_restored[0] = '\0';
959    bigblk = mr_malloc(TAPE_BLOCK_SIZE);
960
961    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
962        log_to_screen("Cannot even open bigfile's info file");
963        return (1);
964    }
965
966    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
967    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
968        sizeof(biggiestruct)) {
969        mr_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
970                bigfileno + 1);
971    }
972    paranoid_fclose(fin);
973
974    mr_asprintf(&checksum, biggiestruct.checksum);
975
976    if (!checksum[0]) {
977        mr_msg(3, "Warning - bigfile %ld does not have a checksum",
978                bigfileno + 1);
979    }
980    mr_free(checksum);
981
982    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
983    {
984        mr_asprintf(&outfile_fname, biggiestruct.filename);
985    } else {
986        mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
987                biggiestruct.filename);
988    }
989
990    /* skip file if we have a selective restore subset & it doesn't match */
991    if (filelist != NULL) {
992        node = find_string_at_node(filelist, biggiestruct.filename);
993        if (!node) {
994            mr_msg(0, "Skipping %s (name isn't in filelist)",
995                    biggiestruct.filename);
996            return (0);
997        } else if (!(node->selected)) {
998            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
999                    biggiestruct.filename);
1000            return (0);
1001        }
1002    }
1003    /* otherwise, continue */
1004
1005    mr_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1006    if (biggiestruct.use_ntfsprog) {
1007        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1008            mr_msg(1,
1009                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1010            mr_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1011            biggiestruct.use_ntfsprog = FALSE;
1012        }
1013    }
1014
1015    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
1016    {
1017        g_loglevel = 4;
1018        use_ntfsprog_hack = TRUE;
1019        mr_msg(2,
1020                "Calling ntfsclone in background because %s is an NTFS /dev entry",
1021                outfile_fname);
1022        mr_asprintf(&ntfsprog_fifo, "/tmp/%d.%d.000", (int) (random() % 32768),
1023                (int) (random() % 32768));
1024        mkfifo(ntfsprog_fifo, 0x770);
1025
1026        file_to_openout = ntfsprog_fifo;
1027        switch (pid = fork()) {
1028        case -1:
1029            fatal_error("Fork failure");
1030        case 0:
1031            mr_msg(3,
1032                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1033                    biggiestruct.filename, ntfsprog_fifo);
1034            res =
1035                feed_outfrom_ntfsprog(biggiestruct.filename,
1036                                      ntfsprog_fifo);
1037            exit(res);
1038            break;
1039        default:
1040            mr_msg(3,
1041                    "feed_into_ntfsprog() called in background --- pid=%ld",
1042                    (long int) (pid));
1043        }
1044    } else {
1045        use_ntfsprog_hack = FALSE;
1046        file_to_openout = outfile_fname;
1047        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1048        {
1049            make_hole_for_file(outfile_fname);
1050        }
1051    }
1052
1053    mr_msg(2, "Reassembling big file %ld (%s)", bigfileno + 1,
1054            outfile_fname);
1055
1056    /*
1057       last slice is zero-length and uncompressed; when we find it, we stop.
1058       We DON'T wait until there are no more slices; if we did that,
1059       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1060     */
1061
1062    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1063            MAX_STR_LEN - 1);
1064    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1065
1066    mr_msg(3, "file_to_openout = %s", file_to_openout);
1067    if (!(fout = fopen(file_to_openout, "w"))) {
1068        log_to_screen(_("Cannot openout file_to_openout - hard disk full?"));
1069        return (1);
1070    }
1071
1072    mr_free(ntfsprog_fifo);
1073    mr_msg(3, "Opened out to %s", outfile_fname);   // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1074
1075    for (sliceno = 1, finished = FALSE; !finished;) {
1076        if (!does_file_exist
1077            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1078            &&
1079            !does_file_exist(slice_fname
1080                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1081            &&
1082            !does_file_exist(slice_fname
1083                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1084            &&
1085            !does_file_exist(slice_fname
1086                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1087            mr_msg(3,
1088                    "Cannot find a data slice or terminator slice on CD %d",
1089                    g_current_media_number);
1090            g_current_media_number++;
1091            mr_msg(2, "Asking for %s #%d so that I may read slice #%ld\n",
1092                    media_descriptor_string(bkpinfo->backup_media_type),
1093                    g_current_media_number, sliceno);
1094            log_to_screen(_("Restoring from %s #%d"),
1095                    bkpinfo->backup_media_string,
1096                    g_current_media_number);
1097            insist_on_this_cd_number(bkpinfo, g_current_media_number);
1098            log_to_screen(_("Continuing to restore."));
1099        } else {
1100            mr_asprintf(&tmp,
1101                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1102            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1103                mr_msg(2,
1104                        "End of bigfile # %ld (slice %ld is the terminator)",
1105                        bigfileno + 1, sliceno);
1106                finished = TRUE;
1107                mr_free(tmp);
1108                continue;
1109            } else {
1110                mr_free(tmp);
1111                if (does_file_exist
1112                    (slice_fname
1113                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1114                    mr_asprintf(&bzip2_command, "lzop");
1115                    mr_asprintf(&suffix, "lzo");
1116                } else
1117                    if (does_file_exist
1118                        (slice_fname
1119                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1120                    mr_asprintf(&bzip2_command, "gzip");
1121                    mr_asprintf(&suffix, "gz");
1122                } else
1123                    if (does_file_exist
1124                        (slice_fname
1125                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1126                    mr_asprintf(&bzip2_command, "bzip2");
1127                    mr_asprintf(&suffix, "bz2");
1128                } else
1129                    if (does_file_exist
1130                        (slice_fname
1131                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1132                    mr_asprintf(&bzip2_command, "");
1133                    mr_asprintf(&suffix, "");
1134                } else {
1135                    log_to_screen(_("OK, that's pretty fsck0red..."));
1136                    return (1);
1137                }
1138            }
1139            if (bzip2_command[0] != '\0') {
1140                mr_strcat(bzip2_command,
1141                        " -dc %s 2>> %s",
1142                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1143                                    suffix), MONDO_LOGFILE);
1144            } else {
1145                mr_free(bzip2_command);
1146                mr_asprintf(&bzip2_command, "cat %s 2>> %s",
1147                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1148                                    suffix), MONDO_LOGFILE);
1149            }
1150            mr_asprintf(&tmp, "Working on %s #%d, file #%ld, slice #%ld",
1151                    bkpinfo->backup_media_string,
1152                    g_current_media_number, bigfileno + 1, sliceno);
1153            mr_msg(2, tmp);
1154            if (!g_text_mode) {
1155                newtDrawRootText(0, g_noof_rows - 2, tmp);
1156                newtRefresh();
1157                update_progress_form(tmp);
1158            }
1159            mr_free(tmp);
1160
1161            if (!(fbzip2 = popen(bzip2_command, "r"))) {
1162                mr_free(bzip2_command);
1163                mr_free(suffix);
1164                fatal_error("Can't run popen command");
1165            }
1166            mr_free(bzip2_command);
1167            mr_free(suffix);
1168
1169            while (!feof(fbzip2)) {
1170                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1171                if (siz > 0) {
1172                    siz = fwrite(bigblk, 1, siz, fout);
1173                }
1174            }
1175            paranoid_pclose(fbzip2);
1176
1177            sliceno++;
1178            g_current_progress++;
1179        }
1180    }
1181    paranoid_fclose(fout);
1182    g_loglevel = old_loglevel;
1183
1184    if (use_ntfsprog_hack) {
1185        mr_msg(3, "Waiting for ntfsclone to finish");
1186        mr_asprintf(&tmp,
1187                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1188        while (system(tmp) == 0) {
1189            sleep(1);
1190        }
1191        mr_free(tmp);
1192        log_it("OK, ntfsclone has really finished");
1193    }
1194
1195    if (strcmp(outfile_fname, "/dev/null")) {
1196        chown(outfile_fname, biggiestruct.properties.st_uid,
1197              biggiestruct.properties.st_gid);
1198        chmod(outfile_fname, biggiestruct.properties.st_mode);
1199        ubuf->actime = biggiestruct.properties.st_atime;
1200        ubuf->modtime = biggiestruct.properties.st_mtime;
1201        utime(outfile_fname, ubuf);
1202    }
1203    mr_free(outfile_fname);
1204    mr_free(bigblk);
1205
1206    return (retval);
1207}
1208
1209
1210/**************************************************************************
1211 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
1212 **************************************************************************/
1213
1214
1215/**
1216 * Restore a biggiefile from the currently opened stream.
1217 * @param bkpinfo The backup information structure. Fields used:
1218 * - @c bkpinfo->restore_path
1219 * - @c bkpinfo->zip_exe
1220 * @param orig_bf_fname The original filename of the biggiefile.
1221 * @param biggiefile_number The number of the biggiefile (starting from 0).
1222 * @param filelist The node structure containing the list of files to be restored.
1223 * If @p orig_bf_fname is not in the list, it will be ignored.
1224 * @return 0 for success (or skip), nonzero for failure.
1225 */
1226int restore_a_biggiefile_from_stream(struct s_bkpinfo *bkpinfo, char *orig_bf_fname, long biggiefile_number, char *orig_checksum,   //UNUSED
1227                                     long long biggiefile_size, //UNUSED
1228                                     struct s_node *filelist,
1229                                     int use_ntfsprog,
1230                                     char *pathname_of_last_file_restored)
1231{
1232    FILE *pout = NULL;
1233    FILE *fin = NULL;
1234
1235  /** mallocs ********/
1236    char *tmp = NULL;
1237    char *tmp1 = NULL;
1238    char *command = NULL;
1239    char *outfile_fname = NULL;
1240    char *ntfsprog_fifo = NULL;
1241    char *file_to_openout = NULL;
1242
1243    struct s_node *node = NULL;
1244
1245    int old_loglevel = 0;
1246    long current_slice_number = 0;
1247    int retval = 0;
1248    int res = 0;
1249    int ctrl_chr = '\0';
1250    long long slice_siz = 0L;
1251    bool dummy_restore = FALSE;
1252    bool use_ntfsprog_hack = FALSE;
1253    pid_t pid;
1254    struct s_filename_and_lstat_info biggiestruct;
1255    struct utimbuf the_utime_buf, *ubuf = NULL;
1256    ubuf = &the_utime_buf;
1257
1258    old_loglevel = g_loglevel;
1259    assert(bkpinfo != NULL);
1260    assert(orig_bf_fname != NULL);
1261    assert(orig_checksum != NULL);
1262
1263    pathname_of_last_file_restored[0] = '\0';
1264    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1265        use_ntfsprog = 1;
1266        mr_msg(1, "%s --- pih=YES", orig_bf_fname);
1267    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1268        use_ntfsprog = 0;
1269        mr_msg(1, "%s --- pih=NO", orig_bf_fname);
1270    } else {
1271        use_ntfsprog = 0;
1272        mr_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1273    }
1274
1275    strncpy(pathname_of_last_file_restored, orig_bf_fname,
1276            MAX_STR_LEN - 1);
1277    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1278
1279    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1280
1281    if (filelist != NULL) {
1282        node = find_string_at_node(filelist, orig_bf_fname);
1283        if (!node) {
1284            dummy_restore = TRUE;
1285            mr_msg(1,
1286                    "Skipping big file %ld (%s) - not in biggielist subset",
1287                    biggiefile_number + 1, orig_bf_fname);
1288            pathname_of_last_file_restored[0] = '\0';
1289        } else if (!(node->selected)) {
1290            dummy_restore = TRUE;
1291            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
1292                    orig_bf_fname);
1293            pathname_of_last_file_restored[0] = '\0';
1294        }
1295    }
1296
1297    if (use_ntfsprog) {
1298        if (strncmp(orig_bf_fname, "/dev/", 5)) {
1299            mr_msg(1, "I was in error when I set use_ntfsprog to TRUE.");
1300            mr_msg(1, "%s isn't even in /dev", orig_bf_fname);
1301            use_ntfsprog = FALSE;
1302        }
1303    }
1304
1305    if (use_ntfsprog) {
1306        g_loglevel = 4;
1307        mr_asprintf(&outfile_fname, orig_bf_fname);
1308        use_ntfsprog_hack = TRUE;
1309        mr_msg(2,
1310                "Calling ntfsclone in background because %s is a /dev entry",
1311                outfile_fname);
1312        mr_asprintf(&ntfsprog_fifo, "%s/%d.%d.000", 
1313                bkpinfo->tmpdir,
1314                (int) (random() % 32768),
1315                (int) (random() % 32768));
1316        mkfifo(ntfsprog_fifo, 0x770);
1317
1318        file_to_openout = ntfsprog_fifo;
1319        switch (pid = fork()) {
1320        case -1:
1321            fatal_error("Fork failure");
1322        case 0:
1323            mr_msg(3,
1324                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1325                    outfile_fname, ntfsprog_fifo);
1326            res = feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1327            exit(res);
1328            break;
1329        default:
1330            mr_msg(3,
1331                    "feed_into_ntfsprog() called in background --- pid=%ld",
1332                    (long int) (pid));
1333        }
1334    } else {
1335        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
1336        {
1337            mr_asprintf(&outfile_fname, orig_bf_fname);
1338        } else                  // biggiefile
1339        {
1340            mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
1341                    orig_bf_fname);
1342        }
1343        use_ntfsprog_hack = FALSE;
1344        file_to_openout = outfile_fname;
1345        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1346        {
1347            make_hole_for_file(outfile_fname);
1348        }
1349        mr_msg(2, "Reassembling big file %ld (%s)",
1350                biggiefile_number + 1, orig_bf_fname);
1351    }
1352
1353    if (dummy_restore) {
1354        mr_free(outfile_fname);
1355        mr_asprintf(&outfile_fname, "/dev/null");
1356    }
1357
1358    if (!bkpinfo->zip_exe[0]) {
1359        mr_asprintf(&command, "cat > \"%s\"", file_to_openout);
1360    } else {
1361        mr_asprintf(&command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1362                file_to_openout, MONDO_LOGFILE);
1363    }
1364    mr_msg(3, "Pipe command = '%s'", command);
1365    mr_free(outfile_fname);
1366    mr_free(ntfsprog_fifo);
1367
1368    /* restore biggiefile, one slice at a time */
1369    if (!(pout = popen(command, "w"))) {
1370        fatal_error("Cannot pipe out");
1371    }
1372    mr_free(command);
1373
1374    malloc_string(tmp1);
1375    for (res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1376         ctrl_chr != BLK_STOP_A_BIGGIE;
1377         res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr)) {
1378        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1379            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1380        }
1381        mr_asprintf(&tmp, "Working on file #%ld, slice #%ld    ",
1382                biggiefile_number + 1, current_slice_number);
1383        mr_msg(2, tmp);
1384        if (!g_text_mode) {
1385            newtDrawRootText(0, g_noof_rows - 2, tmp);
1386            newtRefresh();
1387        }
1388        mr_strip_spaces(tmp);
1389        update_progress_form(tmp);
1390        mr_free(tmp);
1391        if (current_slice_number == 0) {
1392            res =
1393                read_file_from_stream_to_file(bkpinfo,
1394                                              "/tmp/biggie-blah.txt",
1395                                              slice_siz);
1396            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1397                log_OS_error("blah blah");
1398            } else {
1399                if (fread
1400                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1401                     fin) < sizeof(biggiestruct)) {
1402                    mr_msg(2,
1403                            "Warning - unable to get biggiestruct of bigfile #%d",
1404                            biggiefile_number + 1);
1405                }
1406                paranoid_fclose(fin);
1407            }
1408        } else {
1409            res =
1410                read_file_from_stream_to_stream(bkpinfo, pout, slice_siz);
1411        }
1412        retval += res;
1413        res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1414        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1415            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1416        }
1417        current_slice_number++;
1418        g_current_progress++;
1419    }
1420    mr_free(tmp1);
1421    paranoid_pclose(pout);
1422
1423    mr_msg(1, "pathname_of_last_file_restored is now %s",
1424            pathname_of_last_file_restored);
1425
1426    if (use_ntfsprog_hack) {
1427        mr_msg(3, "Waiting for ntfsclone to finish");
1428        mr_asprintf(&tmp,
1429                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1430        while (system(tmp) == 0) {
1431            sleep(1);
1432        }   
1433        mr_free(tmp);
1434        mr_msg(3, "OK, ntfsclone has really finished");
1435    }
1436
1437    mr_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1438    mr_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1439    if (strcmp(outfile_fname, "/dev/null")) {
1440        chmod(outfile_fname, biggiestruct.properties.st_mode);
1441        chown(outfile_fname, biggiestruct.properties.st_uid,
1442              biggiestruct.properties.st_gid);
1443        ubuf->actime = biggiestruct.properties.st_atime;
1444        ubuf->modtime = biggiestruct.properties.st_mtime;
1445        utime(outfile_fname, ubuf);
1446    }
1447
1448    g_loglevel = old_loglevel;
1449    return (retval);
1450}
1451
1452/**************************************************************************
1453 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
1454 **************************************************************************/
1455
1456
1457/**
1458 * Restore @p tarball_fname from CD.
1459 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1460 * This will be used unmodified.
1461 * @param current_tarball_number The number (starting from 0) of the fileset
1462 * we're restoring now.
1463 * @param filelist The node structure containing the list of files to be
1464 * restored. If no file in the afioball is in this list, afio will still be
1465 * called, but nothing will be written.
1466 * @return 0 for success, nonzero for failure.
1467 */
1468int
1469restore_a_tarball_from_CD(char *tarball_fname,
1470                          long current_tarball_number,
1471                          struct s_node *filelist, struct s_bkpinfo *bkpinfo)
1472{
1473    int retval = 0;
1474    int res = 0;
1475    char *p = NULL;
1476
1477  /** malloc **/
1478    char *command = NULL;
1479    char *tmp = NULL;
1480    char *filelist_name = NULL;
1481    char *filelist_subset_fname = NULL;
1482    char *executable = NULL;
1483    char *temp_log = NULL;
1484    long matches = 0;
1485    bool use_star = FALSE;
1486    char *xattr_fname = NULL;
1487    char *acl_fname = NULL;
1488
1489    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1490
1491    mr_msg(5, "Entering");
1492    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1493    mr_asprintf(&command, "mkdir -p %s/tmp", MNT_RESTORING);
1494    run_program_and_log_output(command, 9);
1495    mr_free(command);
1496
1497    mr_asprintf(&filelist_name, MNT_CDROM "/archives/filelist.%ld",
1498            current_tarball_number);
1499    if (length_of_file(filelist_name) <= 2) {
1500        mr_msg(2, "There are _zero_ files in filelist '%s'",
1501                filelist_name);
1502        mr_msg(2,
1503                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1504        mr_msg(2,
1505                "but it's non-critical. It's cosmetic. Don't worry about it.");
1506        retval = 0;
1507        mr_msg(5, "Leaving");
1508        mr_free(filelist_name);
1509        return (retval);
1510    }
1511    if (count_lines_in_file(filelist_name) <= 0
1512        || length_of_file(tarball_fname) <= 0) {
1513        mr_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1514                length_of_file(tarball_fname));
1515        log_to_screen(_("Unable to restore fileset #%ld (CD I/O error)"),
1516                current_tarball_number);
1517        retval = 1;
1518        mr_msg(5, "Leaving");
1519        mr_free(filelist_name);
1520        return (retval);
1521    }
1522
1523    if (filelist) {
1524        mr_asprintf(&filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1525                current_tarball_number);
1526        if ((matches =
1527             save_filelist_entries_in_common(filelist_name, filelist,
1528                                             filelist_subset_fname,
1529                                             use_star))
1530            <= 0) {
1531            mr_msg(1, "Skipping fileset %ld", current_tarball_number);
1532        } else {
1533            mr_msg(3, "Saved fileset %ld's subset to %s",
1534                    current_tarball_number, filelist_subset_fname);
1535        }
1536        log_to_screen("Tarball #%ld --- %ld matches",
1537                current_tarball_number, matches);
1538    }
1539    mr_free(filelist_name);
1540
1541    if (filelist == NULL || matches > 0) {
1542        if (g_getfattr) {
1543            mr_asprintf(&xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1544                MNT_CDROM "/archives", current_tarball_number);
1545        }
1546        if (g_getfacl) {
1547            mr_asprintf(&acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1548                current_tarball_number);
1549        }
1550        if (strstr(tarball_fname, ".bz2")) {
1551            mr_asprintf(&executable, "-P bzip2 -Z");
1552        } else if (strstr(tarball_fname, ".gz")) {
1553            mr_asprintf(&executable, "-P gzip -Z");
1554        } else if (strstr(tarball_fname, ".lzo")) {
1555            mr_asprintf(&executable, "-P lzop -Z");
1556        }
1557
1558        if (executable == NULL) {
1559            mr_asprintf(&tmp, "which %s > /dev/null 2> /dev/null", executable);
1560            if (run_program_and_log_output(tmp, FALSE)) {
1561                log_to_screen
1562                    (_("(compare_a_tarball) Compression program not found - oh no!"));
1563                mr_free(tmp);
1564                mr_free(executable);
1565                mr_free(acl_fname);
1566                mr_free(xattr_fname);
1567                mr_free(filelist_subset_fname);
1568                paranoid_MR_finish(1);
1569            }
1570            mr_free(tmp);
1571        }
1572#ifdef __FreeBSD__
1573#define BUFSIZE 512
1574#else
1575#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1576#endif
1577
1578        if (use_star) {
1579            mr_asprintf(&command,
1580                    "star -x -force-remove -U " STAR_ACL_SZ
1581                    " errctl= file=%s", tarball_fname);
1582            if (strstr(tarball_fname, ".bz2")) {
1583                mr_strcat(command, " -bz");
1584            }
1585        } else {
1586            if (filelist_subset_fname != NULL) {
1587                mr_asprintf(&command,
1588                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1589                        TAPE_BLOCK_SIZE,
1590                        BUFSIZE, executable, filelist_subset_fname,
1591                        tarball_fname);
1592            } else {
1593                mr_asprintf(&command,
1594                        "afio -i -b %ld -c %ld -M 8m %s %s",
1595                        TAPE_BLOCK_SIZE,
1596                        BUFSIZE, executable, tarball_fname);
1597            }
1598        }
1599        mr_free(executable);
1600
1601#undef BUFSIZE
1602        mr_asprintf(&temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1603            (int) (random() % 32768));
1604
1605        mr_strcat(command, " 2>> %s >> %s", temp_log, temp_log);
1606        mr_msg(1, "command = '%s'", command);
1607        unlink(temp_log);
1608        res = system(command);
1609        if (res) {
1610            p = strstr(command, "-acl ");
1611            if (p) {
1612                p[0] = p[1] = p[2] = p[3] = ' ';
1613                mr_msg(1, "new command = '%s'", command);
1614                res = system(command);
1615            }
1616        }
1617        mr_free(command);
1618
1619        if (res && length_of_file(temp_log) < 5) {
1620            res = 0;
1621        }
1622
1623        if (g_getfattr) {
1624            mr_msg(1, "Setting fattr list %s", xattr_fname);
1625            if (length_of_file(xattr_fname) > 0) {
1626                res = set_fattr_list(filelist_subset_fname, xattr_fname);
1627                if (res) {
1628                    log_to_screen
1629                        ("Errors occurred while setting extended attributes");
1630                } else {
1631                    mr_msg(1, "I set xattr OK");
1632                }
1633                retval += res;
1634            }
1635        }
1636        if (g_getfacl) {
1637            mr_msg(1, "Setting acl list %s", acl_fname);
1638            if (length_of_file(acl_fname) > 0) {
1639                res = set_acl_list(filelist_subset_fname, acl_fname);
1640                if (res) {
1641                    log_to_screen
1642                        ("Errors occurred while setting access control lists");
1643                } else {
1644                    mr_msg(1, "I set ACL OK");
1645                }
1646                retval += res;
1647            }
1648        }
1649        if (retval) {
1650            mr_asprintf(&command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1651            system(command);
1652            mr_free(command);
1653            mr_msg(2, "Errors occurred while processing fileset #%d",
1654                    current_tarball_number);
1655        } else {
1656            mr_msg(2, "Fileset #%d processed OK", current_tarball_number);
1657        }
1658        unlink(xattr_fname);
1659        mr_free(xattr_fname);
1660        unlink(acl_fname);
1661        mr_free(acl_fname);
1662        unlink(temp_log);
1663        mr_free(temp_log);
1664    }
1665    if (does_file_exist("/PAUSE")) {
1666        popup_and_OK
1667            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
1668    }
1669    unlink(filelist_subset_fname);
1670    mr_free(filelist_subset_fname);
1671    mr_msg(5, "Leaving");
1672    return (retval);
1673}
1674
1675/**************************************************************************
1676 *END_RESTORE_A_TARBALL_FROM_CD                                           *
1677 **************************************************************************/
1678
1679
1680/**
1681 * Restore a tarball from the currently opened stream.
1682 * @param bkpinfo The backup information structure. Fields used:
1683 * - @c bkpinfo->backup_media_type
1684 * - @c bkpinfo->media_device
1685 * - @c bkpinfo->zip_exe
1686 * @param tarball_fname The filename of the afioball to restore.
1687 * @param current_tarball_number The number (starting from 0) of the fileset
1688 * we're restoring now.
1689 * @param filelist The node structure containing the list of files to be
1690 * restored. If no file in the afioball is in this list, afio will still be
1691 * called, but nothing will be written.
1692 * @param size The size (in @b bytes) of the afioball.
1693 * @return 0 for success, nonzero for failure.
1694 */
1695int
1696restore_a_tarball_from_stream(struct s_bkpinfo *bkpinfo,
1697                              char *tarball_fname,
1698                              long current_tarball_number,
1699                              struct s_node *filelist,
1700                              long long size, char *xattr_fname,
1701                              char *acl_fname)
1702{
1703    int retval = 0;
1704    int res = 0;
1705
1706  /** malloc add ***/
1707    char *tmp = NULL;
1708    char *command = NULL;
1709    char *afio_fname = NULL;
1710    char *filelist_fname = NULL;
1711    char *filelist_subset_fname = NULL;
1712    char *executable = NULL;
1713    long matches = 0;
1714    bool restore_this_fileset = FALSE;
1715    bool use_star = FALSE;
1716
1717    assert(bkpinfo != NULL);
1718    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1719    /* to do it with a file... */
1720    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1721    mr_msg(2, "Restoring from fileset #%ld (%ld KB) on %s #%d",
1722            current_tarball_number, (long) size >> 10,
1723            bkpinfo->backup_media_string,
1724            g_current_media_number);
1725    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1726
1727  /****************************************************************************
1728   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
1729   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
1730   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
1731   ****************************************************************************/
1732    mr_asprintf(&afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1733            current_tarball_number);
1734    mr_asprintf(&filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1735            current_tarball_number);
1736    mr_asprintf(&filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1737            bkpinfo->tmpdir, current_tarball_number);
1738    res = read_file_from_stream_to_file(bkpinfo, afio_fname, size);
1739    if (strstr(tarball_fname, ".star")) {
1740        bkpinfo->use_star = TRUE;
1741    }
1742    if (res) {
1743        mr_msg(1, "Warning - error reading afioball from tape");
1744    }
1745    if (bkpinfo->compression_level != 0) {
1746        if (bkpinfo->use_star) {
1747            mr_asprintf(&executable, " -bz");
1748        } else {
1749            mr_asprintf(&executable, "-P %s -Z", bkpinfo->zip_exe);
1750        }
1751    }
1752
1753    if (!filelist)              // if unconditional restore then restore entire fileset
1754    {
1755        restore_this_fileset = TRUE;
1756    } else                      // If restoring selectively then get TOC from tarball
1757    {
1758        if (strstr(tarball_fname, ".star.")) {
1759            use_star = TRUE;
1760            mr_asprintf(&command, "star -t file=%s %s", afio_fname, executable);
1761        } else {
1762            use_star = FALSE;
1763            mr_asprintf(&command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1764                    executable, afio_fname);
1765        }
1766        mr_strcat(command, " > %s 2>> %s", filelist_fname, MONDO_LOGFILE);
1767        mr_msg(1, "command = %s", command);
1768        if (system(command)) {
1769            mr_msg(4, "Warning - error occurred while retrieving TOC");
1770        }
1771        mr_free(command);
1772
1773        if ((matches =
1774             save_filelist_entries_in_common(filelist_fname, filelist,
1775                                             filelist_subset_fname,
1776                                             use_star))
1777            <= 0 || length_of_file(filelist_subset_fname) < 2) {
1778            if (length_of_file(filelist_subset_fname) < 2) {
1779                mr_msg(1, "No matches found in fileset %ld",
1780                        current_tarball_number);
1781            }
1782            mr_msg(2, "Skipping fileset %ld", current_tarball_number);
1783            restore_this_fileset = FALSE;
1784        } else {
1785            mr_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1786                    matches, current_tarball_number,
1787                    filelist_subset_fname);
1788            restore_this_fileset = TRUE;
1789        }
1790    }
1791    unlink(filelist_fname);
1792    mr_free(filelist_fname);
1793
1794// Concoct the call to star/afio to restore files
1795    if (strstr(tarball_fname, ".star.")) {
1796        // star
1797        if (filelist) {
1798            mr_asprintf(&command, "star -x file=%s %s list=%s 2>> %s", afio_fname, executable, filelist_subset_fname, MONDO_LOGFILE);
1799        } else {
1800            mr_asprintf(&command, "star -x file=%s %s 2>> %s", afio_fname, executable, MONDO_LOGFILE);
1801        }
1802    } else {
1803        // afio
1804        if (filelist) {
1805            mr_asprintf(&command, "afio -i -M 8m -b %ld %s -w %s %s 2>> %s", TAPE_BLOCK_SIZE, executable, filelist_subset_fname, afio_fname, MONDO_LOGFILE);
1806        } else {
1807            mr_asprintf(&command, "afio -i -M 8m -b %ld %s %s 2>> %s", TAPE_BLOCK_SIZE, executable, afio_fname, MONDO_LOGFILE);
1808        }
1809    }
1810    mr_free(executable);
1811
1812    // Call if IF there are files to restore (selectively/unconditionally)
1813    if (restore_this_fileset) {
1814        mr_msg(1, "Calling command='%s'", command);
1815        paranoid_system(command);
1816
1817        if (g_getfattr) {
1818            iamhere("Restoring xattr stuff");
1819            res = set_fattr_list(filelist_subset_fname, xattr_fname);
1820            if (res) {
1821                mr_msg(1, "Errors occurred while setting xattr");
1822            } else {
1823                mr_msg(1, "I set xattr OK");
1824            }
1825            retval += res;
1826        }
1827
1828        if (g_getfacl) {
1829            iamhere("Restoring acl stuff");
1830            res = set_acl_list(filelist_subset_fname, acl_fname);
1831            if (res) {
1832                mr_msg(1, "Errors occurred while setting ACL");
1833            } else {
1834                mr_msg(1, "I set ACL OK");
1835            }
1836            retval += res;
1837        }
1838
1839    } else {
1840        mr_msg(1, "NOT CALLING '%s'", command);
1841    }
1842    mr_free(command);
1843
1844    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1845        log_to_screen(_("Paused after set %ld"), current_tarball_number);
1846        popup_and_OK(_("Pausing. Press ENTER to continue."));
1847    }
1848
1849    unlink(filelist_subset_fname);
1850    unlink(afio_fname);
1851
1852    mr_free(filelist_subset_fname);
1853    mr_free(afio_fname);
1854    return (retval);
1855}
1856
1857/**************************************************************************
1858 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
1859 **************************************************************************/
1860
1861
1862/**
1863 * Restore all biggiefiles from all media in this CD backup.
1864 * The CD with the last afioball should be currently mounted.
1865 * @param bkpinfo The backup information structure. @c backup_media_type is the
1866 * only field used in this function.
1867 * @param filelist The node structure containing the list of files to be
1868 * restored. If a prospective biggiefile is not in this list, it will be ignored.
1869 * @return 0 for success, nonzero for failure.
1870 */
1871int
1872restore_all_biggiefiles_from_CD(struct s_bkpinfo *bkpinfo,
1873                                struct s_node *filelist)
1874{
1875    int retval = 0;
1876    int res = 0;
1877    long noof_biggiefiles = 0L, bigfileno = 0L, total_slices = 0L;
1878    char *tmp = NULL;
1879    char *tmp1 = NULL;
1880    bool just_changed_cds = FALSE, finished = FALSE;
1881    char *xattr_fname = NULL;
1882    char *acl_fname = NULL;
1883    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
1884    char *pathname_of_last_biggie_restored = NULL;
1885    FILE *fbw = NULL;
1886
1887    malloc_string(tmp1);
1888    malloc_string(pathname_of_last_biggie_restored);
1889    assert(bkpinfo != NULL);
1890
1891    mr_asprintf(&biggies_whose_EXATs_we_should_set,
1892            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
1893    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
1894        mr_msg(1, "Warning - cannot openout %s",
1895                biggies_whose_EXATs_we_should_set);
1896    }
1897
1898    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp1);
1899    total_slices = atol(tmp1);
1900    mr_free(tmp1);
1901
1902    mr_asprintf(&tmp, _("Reassembling large files      "));
1903    mvaddstr_and_log_it(g_currentY, 0, tmp);
1904    mr_free(tmp);
1905
1906    if (length_of_file(BIGGIELIST) < 6) {
1907        mr_msg(1, "OK, no biggielist; not restoring biggiefiles");
1908        return (0);
1909    }
1910    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
1911    if (noof_biggiefiles <= 0) {
1912        mr_msg(2,
1913                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
1914        return (0);
1915    }
1916    mr_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
1917
1918    open_progress_form(_("Reassembling large files"),
1919                       _("I am now reassembling all the large files."),
1920                       _("Please wait. This may take some time."),
1921                       "", total_slices);
1922    for (bigfileno = 0, finished = FALSE; !finished;) {
1923        mr_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
1924        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
1925            mr_msg(3,
1926                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
1927            mr_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
1928                    bigfileno + 1,
1929                    bkpinfo->backup_media_string,
1930                    g_current_media_number);
1931            mr_msg(3, "Slicename would have been %s",
1932                    slice_fname(bigfileno + 1, 0, ARCHIVES_PATH, ""));
1933            // I'm not positive 'just_changed_cds' is even necessary...
1934            if (just_changed_cds) {
1935                just_changed_cds = FALSE;
1936                mr_msg(3,
1937                        "I'll continue to scan this CD for bigfiles to be restored.");
1938            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
1939                insist_on_this_cd_number(bkpinfo,
1940                                         ++g_current_media_number);
1941                log_to_screen(_("Restoring from %s #%d"),
1942                        bkpinfo->backup_media_string,
1943                        g_current_media_number);
1944                just_changed_cds = TRUE;
1945            } else {
1946                mr_msg(2, "There was no bigfile #%ld. That's OK.",
1947                        bigfileno + 1);
1948                mr_msg(2, "I'm going to stop restoring bigfiles now.");
1949                finished = TRUE;
1950            }
1951        } else {
1952            just_changed_cds = FALSE;
1953            mr_asprintf(&tmp, _("Restoring big file %ld"), bigfileno + 1);
1954            update_progress_form(tmp);
1955            mr_free(tmp);
1956
1957            res =
1958                restore_a_biggiefile_from_CD(bkpinfo, bigfileno, filelist,
1959                                             pathname_of_last_biggie_restored);
1960            iamhere(pathname_of_last_biggie_restored);
1961            if (fbw && pathname_of_last_biggie_restored[0]) {
1962                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
1963            }
1964            retval += res;
1965            bigfileno++;
1966        }
1967    }
1968
1969    if (fbw) {
1970        fclose(fbw);
1971        if (g_getfattr) {
1972            mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
1973            if (length_of_file(xattr_fname) > 0) {
1974                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
1975            }
1976        }
1977        if (g_getfacl) {
1978            mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
1979            if (length_of_file(acl_fname) > 0) {
1980                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
1981            }
1982        }
1983        mr_free(acl_fname);
1984        mr_free(xattr_fname);
1985    }
1986    mr_free(biggies_whose_EXATs_we_should_set);
1987
1988    if (does_file_exist("/PAUSE")) {
1989        popup_and_OK
1990            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
1991    }
1992    close_progress_form();
1993    if (retval) {
1994        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
1995    } else {
1996        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
1997    }
1998    mr_free(pathname_of_last_biggie_restored);
1999    return (retval);
2000}
2001
2002/**************************************************************************
2003 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2004 **************************************************************************/
2005
2006
2007/**
2008 * Restore all afioballs from all CDs in the backup.
2009 * The first CD should be inserted (if not, it will be asked for).
2010 * @param bkpinfo The backup information structure. @c backup_media_type is the
2011 * only field used in @e this function.
2012 * @param filelist The node structure containing the list of files to be
2013 * restored. If no file in some particular afioball is in this list, afio will
2014 * still be called for that fileset, but nothing will be written.
2015 * @return 0 for success, or the number of filesets that failed.
2016 */
2017int
2018restore_all_tarballs_from_CD(struct s_bkpinfo *bkpinfo,
2019                             struct s_node *filelist)
2020{
2021    int retval = 0;
2022    int res = 0;
2023    int attempts = 0;
2024    long current_tarball_number = 0;
2025    long max_val = 0L;
2026  /**malloc ***/
2027    char *tmp = NULL;
2028    char *tmp1 = NULL;
2029    char *tarball_fname = NULL;
2030    char *progress_str = NULL;
2031    char *comment = NULL;
2032
2033    malloc_string(tmp1);
2034    malloc_string(tarball_fname);
2035    malloc_string(progress_str);
2036    malloc_string(comment);
2037
2038    assert(bkpinfo != NULL);
2039
2040    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2041    mr_msg(2,
2042            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2043    if (g_current_media_number != 1) {
2044        mr_msg(3, "OK, that's jacked up.");
2045        g_current_media_number = 1;
2046    }
2047    insist_on_this_cd_number(bkpinfo, g_current_media_number);
2048    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp1);
2049    max_val = atol(tmp1) + 1;
2050    mr_free(tmp1);
2051
2052    mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2053            bkpinfo->backup_media_string,
2054            g_current_media_number);
2055    log_to_screen(progress_str);
2056    open_progress_form(_("Restoring from archives"),
2057                       _("Restoring data from the archives."),
2058                       _("Please wait. This may take some time."),
2059                       progress_str, max_val);
2060    for (;;) {
2061        insist_on_this_cd_number(bkpinfo, g_current_media_number);
2062        update_progress_form(progress_str);
2063        mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2064                current_tarball_number);
2065        if (!does_file_exist(tarball_fname)) {
2066            mr_free(tarball_fname);
2067            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2068                current_tarball_number);
2069        }
2070        if (!does_file_exist(tarball_fname)) {
2071            mr_free(tarball_fname);
2072            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2073                    current_tarball_number);
2074        }
2075        if (!does_file_exist(tarball_fname)) {
2076            mr_free(tarball_fname);
2077            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2078                    current_tarball_number);
2079        }
2080        if (!does_file_exist(tarball_fname)) {
2081            mr_free(tarball_fname);
2082            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2083                    current_tarball_number);
2084        }
2085        if (!does_file_exist(tarball_fname)) {
2086            mr_free(tarball_fname);
2087            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.",
2088                    current_tarball_number);
2089        }
2090        if (!does_file_exist(tarball_fname)) {
2091            mr_free(tarball_fname);
2092            if (current_tarball_number == 0) {
2093                log_to_screen
2094                    (_("No tarballs. Strange. Maybe you only backed up freakin' big files?"));
2095                mr_free(progress_str);
2096                return (0);
2097            }
2098            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2099                || system("find " MNT_CDROM
2100                          "/archives/slice* > /dev/null 2> /dev/null") ==
2101                0) {
2102                mr_free(tarball_fname);
2103                mr_free(progress_str);
2104                break;
2105            }
2106            g_current_media_number++;
2107            mr_free(progress_str);
2108
2109            mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2110                    bkpinfo->backup_media_string,
2111                    g_current_media_number);
2112            log_to_screen(progress_str);
2113        } else {
2114            mr_free(progress_str);
2115            mr_asprintf(&progress_str,
2116                    _("Restoring from fileset #%ld on %s #%d"),
2117                    current_tarball_number,
2118                    bkpinfo->backup_media_string,
2119                    g_current_media_number);
2120            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2121                 attempts++) {
2122                res =
2123                    restore_a_tarball_from_CD(tarball_fname,
2124                                              current_tarball_number,
2125                                              filelist, bkpinfo);
2126            }
2127            mr_asprintf(&tmp, _("%s #%d, fileset #%ld - restore "),
2128                    media_descriptor_string(bkpinfo->backup_media_type),
2129                    g_current_media_number, current_tarball_number);
2130            if (res) {
2131                mr_strcat(tmp, _("reported errors"));
2132            } else {
2133                mr_strcat(tmp, _("succeeded"));
2134            }
2135            if (attempts > 1) {
2136                mr_strcat(tmp, _(" (%d attempts) - review logs"), attempts);
2137            }
2138            if (attempts > 1) {
2139                log_to_screen(tmp);
2140            }
2141            mr_free(tmp);
2142
2143            retval += res;
2144            current_tarball_number++;
2145            g_current_progress++;
2146        }
2147        mr_free(tarball_fname);
2148    }
2149    mr_free(progress_str);
2150    close_progress_form();
2151
2152    if (retval) {
2153        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2154    } else {
2155        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2156    }
2157    return (retval);
2158}
2159
2160/**************************************************************************
2161 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2162 **************************************************************************/
2163
2164
2165/**
2166 * Restore all biggiefiles from the currently opened stream.
2167 * @param bkpinfo The backup information structure. Passed to other functions.
2168 * @param filelist The node structure containing the list of files to be
2169 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2170 * @return 0 for success, or the number of biggiefiles that failed.
2171 */
2172int
2173restore_all_biggiefiles_from_stream(struct s_bkpinfo *bkpinfo,
2174                                    struct s_node *filelist)
2175{
2176    long noof_biggiefiles = 0L;
2177    long current_bigfile_number = 0L;
2178    long total_slices = 0L;
2179
2180    int retval = 0;
2181    int res = 0;
2182    int ctrl_chr = 0;
2183
2184  /** malloc add ****/
2185    char *tmp = NULL;
2186    char *biggie_fname = NULL;
2187    char *biggie_cksum = NULL;
2188    char *xattr_fname = NULL;
2189    char *acl_fname = NULL;
2190    char *pathname_of_last_biggie_restored = NULL;
2191    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
2192    long long biggie_size = (long long)0;
2193    FILE *fbw;
2194
2195    assert(bkpinfo != NULL);
2196
2197    malloc_string(tmp);
2198    malloc_string(biggie_fname);
2199    malloc_string(biggie_cksum);
2200    malloc_string(pathname_of_last_biggie_restored);
2201    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2202    total_slices = atol(tmp);
2203    mr_free(tmp);
2204
2205    mr_asprintf(&tmp, "Reassembling large files      ");
2206    if (g_getfattr) {
2207        mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2208    }
2209    if (g_getfacl) {
2210        mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2211    }
2212    mvaddstr_and_log_it(g_currentY, 0, tmp);
2213    mr_free(tmp);
2214
2215    mr_asprintf(&biggies_whose_EXATs_we_should_set,
2216            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2217    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2218        mr_msg(1, "Warning - cannot openout %s",
2219                biggies_whose_EXATs_we_should_set);
2220    }
2221    // get xattr and acl files if they're there
2222    res =
2223        read_header_block_from_stream(&biggie_size, biggie_fname,
2224                                      &ctrl_chr);
2225    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2226        res =
2227            read_EXAT_files_from_tape(bkpinfo, &biggie_size, biggie_fname,
2228                                      &ctrl_chr, xattr_fname, acl_fname);
2229    }
2230
2231    noof_biggiefiles = atol(biggie_fname);
2232    mr_msg(2, "OK, there are %ld biggiefiles in the archives",
2233            noof_biggiefiles);
2234    open_progress_form(_("Reassembling large files"),
2235                       _("I am now reassembling all the large files."),
2236                       _("Please wait. This may take some time."),
2237                       "", total_slices);
2238
2239    for (res =
2240         read_header_block_from_stream(&biggie_size, biggie_fname,
2241                                       &ctrl_chr);
2242         ctrl_chr != BLK_STOP_BIGGIEFILES;
2243         res =
2244         read_header_block_from_stream(&biggie_size, biggie_fname,
2245                                       &ctrl_chr)) {
2246        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2247            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2248            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2249        }
2250        /* BERLIOS: useless
2251        p = strrchr(biggie_fname, '/');
2252        if (!p) {
2253            p = biggie_fname;
2254        } else {
2255            p++;
2256        }
2257        */
2258        mr_asprintf(&tmp, _("Restoring big file %ld (%lld K)"),
2259                current_bigfile_number + 1, biggie_size / 1024);
2260        update_progress_form(tmp);
2261        mr_free(tmp);
2262
2263        res = restore_a_biggiefile_from_stream(bkpinfo, biggie_fname,
2264                                               current_bigfile_number,
2265                                               biggie_cksum,
2266                                               biggie_size,
2267                                               filelist, ctrl_chr,
2268                                               pathname_of_last_biggie_restored);
2269        mr_msg(1, "I believe I have restored %s",
2270                pathname_of_last_biggie_restored);
2271        if (fbw && pathname_of_last_biggie_restored[0]) {
2272            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2273        }
2274        mr_free(pathname_of_last_biggie_restored);
2275
2276        retval += res;
2277        current_bigfile_number++;
2278
2279    }
2280    if (current_bigfile_number != noof_biggiefiles
2281        && noof_biggiefiles != 0) {
2282        mr_msg(1, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2283                current_bigfile_number, noof_biggiefiles);
2284    } else {
2285        mr_msg(1, "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2286                noof_biggiefiles, current_bigfile_number);
2287    }
2288
2289    if (fbw) {
2290        fclose(fbw);
2291        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2292            iamhere("Setting biggie-EXATs");
2293            if (g_getfattr) {
2294                if (length_of_file(xattr_fname) > 0) {
2295                    mr_msg(1, "set_fattr_List(%s,%s)",
2296                        biggies_whose_EXATs_we_should_set, xattr_fname);
2297                    set_fattr_list(biggies_whose_EXATs_we_should_set,
2298                               xattr_fname);
2299                }
2300            }
2301            if (g_getfacl) {
2302                if (length_of_file(acl_fname) > 0) {
2303                    mr_msg(1, "set_acl_list(%s,%s)",
2304                            biggies_whose_EXATs_we_should_set, acl_fname);
2305                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2306                }
2307            }
2308        } else {
2309            iamhere
2310                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2311        }
2312    }
2313    mr_free(xattr_fname);
2314    mr_free(acl_fname);
2315    mr_free(biggies_whose_EXATs_we_should_set);
2316
2317    if (does_file_exist("/PAUSE")) {
2318        popup_and_OK
2319            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2320    }
2321
2322    close_progress_form();
2323    if (retval) {
2324        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2325    } else {
2326        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2327    }
2328    mr_free(biggie_fname);
2329    mr_free(biggie_cksum);
2330    return (retval);
2331}
2332
2333/**************************************************************************
2334 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2335 **************************************************************************/
2336
2337
2338/**
2339 * Restore all afioballs from the currently opened tape stream.
2340 * @param bkpinfo The backup information structure. Fields used:
2341 * - @c bkpinfo->backup_media_type
2342 * - @c bkpinfo->restore_path
2343 * @param filelist The node structure containing the list of files to be
2344 * restored. If no file in an afioball is in this list, afio will still be
2345 * called for that fileset, but nothing will be written.
2346 * @return 0 for success, or the number of filesets that failed.
2347 */
2348int
2349restore_all_tarballs_from_stream(struct s_bkpinfo *bkpinfo,
2350                                 struct s_node *filelist)
2351{
2352    int retval = 0;
2353    int res = 0;
2354    long current_afioball_number = 0;
2355    int ctrl_chr = 0;
2356    long max_val = 0L /*, total_noof_files */ ;
2357
2358  /** malloc **/
2359    char *tmp = NULL;
2360    char *progress_str = NULL;
2361    char *tmp_fname = NULL;
2362    char *xattr_fname = NULL;
2363    char *acl_fname = NULL;
2364
2365    long long tmp_size = 0L;
2366
2367    malloc_string(tmp_fname);
2368    malloc_string(tmp);
2369    assert(bkpinfo != NULL);
2370    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2371    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2372    max_val = atol(tmp) + 1;
2373    mr_free(tmp);
2374
2375    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2376
2377    run_program_and_log_output("pwd", 5);
2378
2379    mr_asprintf(&progress_str, _("Restoring from media #%d"),
2380            g_current_media_number);
2381    log_to_screen(progress_str);
2382    open_progress_form(_("Restoring from archives"),
2383                       _("Restoring data from the archives."),
2384                       _("Please wait. This may take some time."),
2385                       progress_str, max_val);
2386
2387    mr_msg(3, "hey");
2388
2389    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2390    if (res) {
2391        mr_msg(2, "Warning - error reading afioball from tape");
2392    }
2393    retval += res;
2394    if (ctrl_chr != BLK_START_AFIOBALLS) {
2395        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2396    }
2397    mr_msg(2, "ho");
2398    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2399    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2400        update_progress_form(progress_str);
2401        if (g_getfattr) {
2402            mr_asprintf(&xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2403                current_afioball_number);
2404            unlink(xattr_fname);
2405        }
2406        if (g_getfacl) {
2407            mr_asprintf(&acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2408                current_afioball_number);
2409            unlink(acl_fname);
2410        }
2411        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2412            iamhere("Reading EXAT files from tape");
2413            res =
2414                read_EXAT_files_from_tape(bkpinfo, &tmp_size, tmp_fname,
2415                                          &ctrl_chr, xattr_fname,
2416                                          acl_fname);
2417        }
2418        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2419            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2420        }
2421        /* BERLIOS: useless ?
2422        mr_asprintf(&tmp,
2423                _("Restoring from fileset #%ld (name=%s, size=%ld K)"),
2424                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2425                */
2426        res =
2427            restore_a_tarball_from_stream(bkpinfo, tmp_fname,
2428                                          current_afioball_number,
2429                                          filelist, tmp_size, xattr_fname,
2430                                          acl_fname);
2431        retval += res;
2432        if (res) {
2433            log_to_screen("Fileset %ld - errors occurred",
2434                    current_afioball_number);
2435        }
2436        res =
2437            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2438        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2439            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2440        }
2441
2442        current_afioball_number++;
2443        g_current_progress++;
2444
2445        mr_free(progress_str);
2446        mr_asprintf(&progress_str, _("Restoring from fileset #%ld on %s #%d"),
2447                current_afioball_number,
2448                bkpinfo->backup_media_string,
2449                g_current_media_number);
2450        res =
2451            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2452        if (g_getfattr) {
2453            unlink(xattr_fname);
2454        }
2455        if (g_getfacl) {
2456            unlink(acl_fname);
2457        }
2458        mr_free(xattr_fname);
2459        mr_free(acl_fname);
2460    }                           // next
2461    mr_free(progress_str);
2462    mr_free(tmp_fname);
2463
2464    mr_msg(1, "All done with afioballs");
2465    close_progress_form();
2466    if (retval) {
2467        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2468    } else {
2469        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2470    }
2471    return (retval);
2472}
2473
2474/**************************************************************************
2475 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2476 **************************************************************************/
2477
2478/* @} - end of LLrestoreGroup */
2479
2480
2481/**
2482 * Restore all files in @p filelist.
2483 * @param bkpinfo The backup information structure. Most fields are used.
2484 * @param filelist The node structure containing the list of files to be
2485 * restored.
2486 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2487 * @ingroup restoreGroup
2488 */
2489int restore_everything(struct s_bkpinfo *bkpinfo, struct s_node *filelist)
2490{
2491    int resA;
2492    int resB;
2493
2494  /** mallco ***/
2495    char *cwd = NULL;
2496    char *newpath = NULL;
2497    char *tmp = NULL;
2498    assert(bkpinfo != NULL);
2499
2500    malloc_string(cwd);
2501    malloc_string(newpath);
2502    mr_msg(2, "restore_everything() --- starting");
2503    g_current_media_number = 1;
2504    /* BERLIOS: should test return value, or better change the function */
2505    getcwd(cwd, MAX_STR_LEN - 1);
2506    mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->restore_path);
2507    run_program_and_log_output(tmp, FALSE);
2508    mr_free(tmp);
2509
2510    mr_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2511    chdir(bkpinfo->restore_path);
2512    /* BERLIOS: should test return value, or better change the function */
2513    getcwd(newpath, MAX_STR_LEN - 1);
2514    mr_msg(1, "path is now %s", newpath);
2515    mr_msg(1, "restoring everything");
2516    if (!find_home_of_exe("petris") && !g_text_mode) {
2517        newtDrawRootText(0, g_noof_rows - 2,
2518                         _("Press ALT-<left cursor> twice to play Petris :-) "));
2519        newtRefresh();
2520    }
2521    mvaddstr_and_log_it(g_currentY, 0, _("Preparing to read your archives"));
2522    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2523        mount_cdrom(bkpinfo);
2524        mvaddstr_and_log_it(g_currentY++, 0,
2525                            _("Restoring OS and data from streaming media"));
2526        if (bkpinfo->backup_media_type == cdstream) {
2527            openin_cdstream(bkpinfo);
2528        } else {
2529            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->
2530                                                         media_device);
2531            openin_tape(bkpinfo);
2532        }
2533        resA = restore_all_tarballs_from_stream(bkpinfo, filelist);
2534        resB = restore_all_biggiefiles_from_stream(bkpinfo, filelist);
2535        if (bkpinfo->backup_media_type == cdstream) {
2536            closein_cdstream(bkpinfo);
2537        } else {
2538            closein_tape(bkpinfo);
2539        }
2540    } else {
2541        mvaddstr_and_log_it(g_currentY++, 0,
2542                            _("Restoring OS and data from CD       "));
2543        mount_cdrom(bkpinfo);
2544        resA = restore_all_tarballs_from_CD(bkpinfo, filelist);
2545        resB = restore_all_biggiefiles_from_CD(bkpinfo, filelist);
2546    }
2547    chdir(cwd);
2548    if (resA + resB) {
2549        log_to_screen(_("Errors occurred while data was being restored."));
2550    }
2551    if (length_of_file("/etc/raidtab") > 0) {
2552        mr_msg(2, "Copying local raidtab to restored filesystem");
2553        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2554                                   "/etc/raidtab", FALSE);
2555    }
2556    kill_petris();
2557    mr_msg(2, "restore_everything() --- leaving");
2558    mr_free(cwd);
2559    mr_free(newpath);
2560    return (resA + resB);
2561}
2562
2563/**************************************************************************
2564 *END_RESTORE_EVERYTHING                                                  *
2565 **************************************************************************/
2566
2567
2568/**
2569 * @brief Haha. You wish! (This function is not implemented :-)
2570 */
2571int
2572restore_live_from_monitas_server(struct s_bkpinfo *bkpinfo,
2573                                 char *monitas_device,
2574                                 char *restore_this_directory,
2575                                 char *restore_here)
2576     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2577{
2578    FILE *fout;
2579    int retval = 0;
2580    int i;
2581    int j;
2582    struct mountlist_itself the_mountlist;
2583    static struct raidlist_itself the_raidlist;
2584  /** malloc **/
2585    char tmp[MAX_STR_LEN + 1];
2586    char command[MAX_STR_LEN + 1];
2587    char datablock[256 * 1024];
2588    char datadisks_fname[MAX_STR_LEN + 1];
2589    long k;
2590    long length;
2591    long long llt;
2592    struct s_node *filelist = NULL;
2593    assert(bkpinfo != NULL);
2594    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2595    assert(restore_this_directory != NULL);
2596    assert(restore_here != NULL);
2597
2598    sprintf(tmp, "restore_here = '%s'", restore_here);
2599
2600    mr_msg(2, tmp);
2601
2602    mr_msg(2, "restore_live_from_monitas_server() - starting");
2603    unlink("/tmp/mountlist.txt");
2604    unlink("/tmp/filelist.full");
2605    unlink("/tmp/biggielist.txt");
2606    if (restore_here[0] == '\0') {
2607        strcpy(bkpinfo->restore_path, MNT_RESTORING);
2608    } else {
2609        strcpy(bkpinfo->restore_path, restore_here);
2610    }
2611    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2612    sprintf(tmp, "FYI - data will be restored to %s",
2613            bkpinfo->restore_path);
2614    mr_msg(3, tmp);
2615    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2616    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2617            (int) (random() % 32768));
2618    chdir(bkpinfo->tmpdir);
2619
2620    sprintf(command, "cat %s", monitas_device);
2621    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
2622    if (!(fout = fopen(datadisks_fname, "w"))) {
2623        log_OS_error(datadisks_fname);
2624        return (1);
2625    }
2626    for (i = 0; i < 32; i++) {
2627        for (j = 0; j < 4; j++) {
2628            for (length = k = 0; length < 256 * 1024; length += k) {
2629                k = fread(datablock + length, 1, 256 * 1024 - length,
2630                          g_tape_stream);
2631            }
2632            fwrite(datablock, 1, length, fout);
2633            g_tape_posK += length;
2634        }
2635    }
2636    paranoid_fclose(fout);
2637    sprintf(command,
2638            "tar -zxvf %s tmp/mondo-restore.cfg tmp/mountlist.txt tmp/filelist.full tmp/biggielist.txt",
2639            datadisks_fname);
2640    run_program_and_log_output(command, 4);
2641    read_header_block_from_stream(&llt, tmp, &i);
2642    read_header_block_from_stream(&llt, tmp, &i);
2643
2644    unlink(datadisks_fname);
2645    read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
2646    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
2647
2648
2649    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2650    iamhere("FIXME");
2651    fatal_error("This will fail");
2652    sprintf(command,
2653            "grep -E '^%s.*$' %s > %s",
2654            restore_this_directory, g_filelist_full, g_filelist_full);
2655    if (system(command)) {
2656        retval++;
2657        log_to_screen
2658            ("Error(s) occurred while processing filelist and wildcard");
2659    }
2660    iamhere("FIXME");
2661    fatal_error("This will fail");
2662    sprintf(command,
2663            "grep -E '^%s.*$' %s > %s",
2664            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2665    if (system(command)) {
2666        mr_msg(1,
2667                "Error(s) occurred while processing biggielist and wildcard");
2668    }
2669    sprintf(command, "touch %s", g_biggielist_txt);
2670    run_program_and_log_output(command, FALSE);
2671//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2672    retval += restore_everything(bkpinfo, filelist);
2673    free_filelist(filelist);
2674    mr_msg(2, "--------End of restore_live_from_monitas_server--------");
2675    return (retval);
2676}
2677
2678/**************************************************************************
2679 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
2680 **************************************************************************/
2681
2682
2683
2684
2685extern void wait_until_software_raids_are_prepped(char *, int);
2686
2687char which_restore_mode(void);
2688
2689
2690/**
2691 * Log a "don't panic" message to the logfile.
2692 */
2693void welcome_to_mondorestore()
2694{
2695    mr_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2696    mr_msg(0,
2697            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2698    mr_msg(0,
2699            "don't break out in a cold sweat just because you see a few  ");
2700    mr_msg(0,
2701            "error messages in the log. Read them; analyze them; see if  ");
2702    mr_msg(0,
2703            "they are significant; above all, verify your backups! Please");
2704    mr_msg(0,
2705            "attach a compressed copy of this log to any e-mail you send ");
2706    mr_msg(0,
2707            "to the Mondo mailing list when you are seeking technical    ");
2708    mr_msg(0,
2709            "support. Without it, we can't help you.            - DevTeam");
2710    mr_msg(0,
2711            "------------------------------------------------------------");
2712    mr_msg(0,
2713            "BTW, despite (or perhaps because of) the wealth of messages,");
2714    mr_msg(0,
2715            "some users are inclined to stop reading this log.  If Mondo ");
2716    mr_msg(0,
2717            "stopped for some reason, chances are it's detailed here.    ");
2718    mr_msg(0,
2719            "More than likely there's a message near the end of this     ");
2720    mr_msg(0,
2721            "log that will tell you what is wrong.  Please read it!      ");
2722    mr_msg(0,
2723            "------------------------------------------------------------");
2724}
2725
2726
2727/**
2728 * Restore the user's data.
2729 * What did you think it did, anyway? :-)
2730 */
2731int main(int argc, char *argv[])
2732{
2733    FILE *fin = NULL;
2734    FILE *fout = NULL;
2735    int retval = 0;
2736    int res = 0;
2737    char *tmp = NULL;
2738
2739    struct mountlist_itself *mountlist = NULL;
2740    struct raidlist_itself *raidlist = NULL;
2741    struct s_bkpinfo *bkpinfo = NULL;
2742    struct s_node *filelist = NULL;
2743    char *a = NULL, *b = NULL;
2744    bool run_postnuke = FALSE;
2745
2746#ifdef ENABLE_NLS
2747    setlocale(LC_ALL, "");
2748    (void) textdomain("mondo");
2749#endif
2750
2751    if (getuid() != 0) {
2752        fprintf(stderr, _("Please run as root.\n"));
2753        exit(127);
2754    }
2755
2756    g_loglevel = DEFAULT_MR_LOGLEVEL;
2757
2758/* Configure global variables */
2759#ifdef __FreeBSD__
2760    if (strstr
2761        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2762         "textonly"))
2763#else
2764    if (strstr
2765        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2766         "textonly"))
2767#endif
2768    {
2769        g_text_mode = TRUE;
2770        mr_msg(1, "TEXTONLY MODE");
2771    } else {
2772        g_text_mode = FALSE;
2773    }                           // newt :-)
2774    bkpinfo = mr_malloc(sizeof(struct s_bkpinfo));
2775    mountlist = mr_malloc(sizeof(struct mountlist_itself));
2776    raidlist = mr_malloc(sizeof(struct raidlist_itself));
2777
2778    malloc_libmondo_global_strings();
2779
2780    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2781    make_hole_for_dir(g_tmpfs_mountpt);
2782    g_current_media_number = 1; // precaution
2783
2784    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2785    run_program_and_log_output("mkdir -p /mnt/floppy", FALSE);
2786
2787    malloc_string(a);
2788    malloc_string(b);
2789    setup_MR_global_filenames(bkpinfo); // malloc() and set globals, using bkpinfo->tmpdir etc.
2790    reset_bkpinfo(bkpinfo);
2791    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2792    strcpy(bkpinfo->backup_media_string,"");
2793    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2794    if (am_I_in_disaster_recovery_mode()) {
2795        run_program_and_log_output("mount / -o remount,rw", 2);
2796    }                           // for b0rken distros
2797    g_main_pid = getpid();
2798    srandom((int) (time(NULL)));
2799    register_pid(getpid(), "mondo");
2800    set_signals(TRUE);
2801    g_kernel_version = get_kernel_version();
2802
2803    mr_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2804    if (strlen(g_mountlist_fname) < 3) {
2805        fatal_error
2806            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2807    }
2808    mkdir(MNT_CDROM, 0x770);
2809
2810/* Backup original mountlist.txt */
2811    mr_asprintf(&tmp, "%s.orig", g_mountlist_fname);
2812    if (!does_file_exist(g_mountlist_fname)) {
2813        mr_msg(2,
2814                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2815                __LINE__, g_mountlist_fname);
2816    } else if (!does_file_exist(tmp)) {
2817        mr_free(tmp);
2818        mr_asprintf(&tmp, "cp -f %s %s.orig", g_mountlist_fname,
2819                g_mountlist_fname);
2820        run_program_and_log_output(tmp, FALSE);
2821    }
2822    mr_free(tmp);
2823
2824/* Init directories */
2825    make_hole_for_dir(bkpinfo->tmpdir);
2826    mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->tmpdir);
2827    run_program_and_log_output(tmp, FALSE);
2828    mr_free(tmp);
2829
2830    make_hole_for_dir("/var/log");
2831    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
2832    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2833    run_program_and_log_output
2834        ("ln -sf /var/log/mondo-archive.log /tmp/mondo-restore.log",
2835         FALSE);
2836
2837    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2838
2839    /* Init GUI */
2840    malloc_libmondo_global_strings();
2841    setup_newt_stuff();         /* call newtInit and setup screen log */
2842    welcome_to_mondorestore();
2843    if (bkpinfo->disaster_recovery) {
2844        mr_msg(1, "I am in disaster recovery mode");
2845    } else {
2846        mr_msg(1, "I am in normal, live mode");
2847    }
2848
2849    iamhere("what time is it");
2850
2851    /* Process command-line parameters */
2852    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
2853#ifdef __FreeBSD__
2854        system("mv -f /tmp/raidconf.txt /etc/raidtab");
2855        if (!does_file_exist("/etc/raidtab"))
2856            system("vinum printconfig > /etc/raidtab");
2857#endif
2858        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2859        if (!does_file_exist(g_mountlist_fname)) {
2860            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2861        }
2862        res = let_user_edit_the_mountlist(bkpinfo, mountlist, raidlist);
2863#ifdef __FreeBSD__
2864        system("mv -f /etc/raidtab /tmp/raidconf.txt");
2865#endif
2866        paranoid_MR_finish(res);
2867    }
2868
2869    g_loglevel = DEFAULT_MR_LOGLEVEL;
2870    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
2871        fout = fopen("/tmp/out.txt", "w");
2872        fput_string_one_char_at_a_time(stderr, argv[2]);
2873        finish(0);
2874    }
2875
2876    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
2877        make_grub_install_scriptlet(argv[2]);
2878        finish(0);
2879    }
2880
2881    if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
2882        if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
2883            system("mount " MNT_CDROM);
2884        }
2885        bkpinfo->compression_level = 1;
2886        g_current_media_number = 2;
2887        strcpy(bkpinfo->restore_path, "/tmp/TESTING");
2888        bkpinfo->backup_media_type = dvd;
2889        open_progress_form(_("Reassembling /dev/hda1"),
2890                           _("Shark is a bit of a silly person."),
2891                           _("Please wait. This may take some time."),
2892                           "", 1999);
2893        system("rm -Rf /tmp/*pih*");
2894
2895        malloc_string(tmp);
2896        restore_a_biggiefile_from_CD(bkpinfo, 42, NULL, tmp);
2897        mr_free(tmp);
2898    }
2899
2900    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
2901        g_loglevel = 6;
2902        filelist = load_filelist(argv[2]);
2903        if (!filelist) {
2904            fatal_error("Failed to load filelist");
2905        }
2906        toggle_node_selection(filelist, FALSE);
2907        toggle_all_root_dirs_on(filelist);
2908        // BERLIOS: /usr/lib ???
2909        toggle_path_selection(filelist, "/usr/share", TRUE);
2910        save_filelist(filelist, "/tmp/out.txt");
2911        mr_asprintf(&a, argv[3]);
2912        mr_asprintf(&b, argv[4]);
2913
2914        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
2915        free_filelist(filelist);
2916        mr_free(a);
2917        mr_free(b);
2918        printf("res = %d", res);
2919        finish(0);
2920    }
2921
2922    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
2923        popup_changelist_from_file(argv[2]);
2924        paranoid_MR_finish(0);
2925    }
2926
2927    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
2928        mr_msg(1, "SCORE");
2929        g_loglevel = 10;
2930        if (strstr(argv[2], "save")) {
2931            mr_msg(1, "Saving from %s to %s", argv[3], argv[4]);
2932            fin = fopen(argv[3], "r");
2933            fout = fopen(argv[4], "w");
2934            copy_from_src_to_dest(fin, fout, 'w');
2935            fclose(fin);
2936            fin = fopen(argv[3], "r");
2937            copy_from_src_to_dest(fin, fout, 'w');
2938            fclose(fout);
2939            fclose(fin);
2940        } else if (strstr(argv[2], "restore")) {
2941            fout = fopen(argv[3], "w");
2942            fin = fopen(argv[4], "r");
2943            copy_from_src_to_dest(fout, fin, 'r');
2944            fclose(fin);
2945            fin = fopen(argv[4], "r");
2946            copy_from_src_to_dest(fout, fin, 'r');
2947            fclose(fout);
2948            fclose(fin);
2949        } else {
2950            fatal_error("Unknown additional param");
2951        }
2952        finish(0);
2953    }
2954
2955    if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
2956        wait_until_software_raids_are_prepped(argv[2], 100);
2957        finish(0);
2958    }
2959
2960    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
2961        finish(create_raidtab_from_mdstat(argv[2]));
2962    }
2963
2964
2965    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
2966        retval = run_grub(FALSE, "/dev/hda");
2967        if (retval) {
2968            log_to_screen(_("Failed to write Master Boot Record"));
2969        }
2970        paranoid_MR_finish(0);
2971    }
2972    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
2973        g_current_media_number = atoi(argv[2]);
2974        pause_and_ask_for_cdr(5, NULL);
2975        paranoid_MR_finish(0);
2976    } else if (!bkpinfo->disaster_recovery) {   // live!
2977        if (argc != 1) {
2978            popup_and_OK
2979                (_("Live mode doesn't support command-line parameters yet."));
2980            paranoid_MR_finish(1);
2981        }
2982        mr_msg(1, "I am in normal, live mode.");
2983        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
2984        mount_boot_if_necessary();  /* for Gentoo users */
2985        mr_msg(2, "Still here.");
2986        if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
2987            g_restoring_live_from_cd = TRUE;
2988        }
2989        if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
2990            retval =
2991                restore_live_from_monitas_server(bkpinfo,
2992                                                 argv[2],
2993                                                 argv[3], argv[4]);
2994        } else {
2995            mr_msg(2, "Calling restore_to_live_filesystem()");
2996            retval = restore_to_live_filesystem(bkpinfo);
2997        }
2998        mr_msg(2, "Still here. Yay.");
2999        if (strlen(bkpinfo->tmpdir) > 0) {
3000            mr_asprintf(&tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3001            run_program_and_log_output(tmp, FALSE);
3002            mr_free(tmp);
3003        }
3004        unmount_boot_if_necessary();    /* for Gentoo users */
3005        paranoid_MR_finish(retval);
3006    } else {
3007        /* Disaster recovery mode (must be) */
3008        mr_msg(1, "I must be in disaster recovery mode.");
3009        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3010        if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
3011            log_to_screen(_("Uh, that hasn't been implemented yet."));
3012            paranoid_MR_finish(1);
3013        }
3014
3015        iamhere("About to call load_mountlist and load_raidtab");
3016        strcpy(bkpinfo->restore_path, MNT_RESTORING);
3017        read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
3018        retval = load_mountlist(mountlist, g_mountlist_fname);
3019        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3020        iamhere
3021            ("Returned from calling load_mountlist and load_raidtab successfully");
3022
3023        if (argc > 1
3024            && (strcmp(argv[1], "--compare") == 0
3025                || strcmp(argv[1], "--nuke") == 0)) {
3026            if (bkpinfo->backup_media_type == nfs
3027                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3028                mr_msg(1, "Mounting nfs dir");
3029                sprintf(bkpinfo->isodir, "/tmp/isodir");
3030                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3031                mr_asprintf(&tmp, "mount %s -t nfs -o nolock /tmp/isodir",
3032                        bkpinfo->nfs_mount);
3033                run_program_and_log_output(tmp, 1);
3034                mr_free(tmp);
3035            }
3036        }
3037
3038
3039        if (retval) {
3040            log_to_screen
3041                (_("Warning - load_raidtab_into_raidlist returned an error"));
3042        }
3043
3044
3045        mr_msg(1, "Send in the clowns.");
3046
3047        if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
3048            mr_msg(0, "Partitioning only.");
3049            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3050            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3051            load_mountlist(mountlist, g_mountlist_fname);
3052            res = partition_everything(mountlist);
3053            finish(res);
3054        }
3055
3056        if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3057            mr_msg(0, "Formatting only.");
3058            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3059            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3060            load_mountlist(mountlist, g_mountlist_fname);
3061            res = format_everything(mountlist, FALSE, raidlist);
3062            finish(res);
3063        }
3064
3065        if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3066            mr_msg(0, "Stopping LVM and RAID");
3067            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3068            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3069            load_mountlist(mountlist, g_mountlist_fname);
3070            res = do_my_funky_lvm_stuff(TRUE, FALSE);
3071            res += stop_all_raid_devices(mountlist);
3072            finish(res);
3073        }
3074
3075        if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3076            iamhere("nuking");
3077            retval += nuke_mode(bkpinfo, mountlist, raidlist);
3078        } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3079            iamhere("catchall");
3080            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3081        } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3082            iamhere("compare");
3083            retval += compare_mode(bkpinfo, mountlist, raidlist);
3084        } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3085            iamhere("iso");
3086            retval = iso_mode(bkpinfo, mountlist, raidlist, FALSE);
3087        } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3088            iamhere("mbr");
3089            retval = mount_all_devices(mountlist, TRUE);
3090            if (!retval) {
3091                retval += run_boot_loader(FALSE);
3092                retval += unmount_all_devices(mountlist);
3093            }
3094            if (retval) {
3095                log_to_screen(_("Failed to write Master Boot Record"));
3096            }
3097        } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3098            iamhere("isonuke");
3099            retval = iso_mode(bkpinfo, mountlist, raidlist, TRUE);
3100        } else if (argc != 1) {
3101            log_to_screen(_("Invalid parameters"));
3102            paranoid_MR_finish(1);
3103        } else {
3104            iamhere("catchall (no mode specified in command-line call");
3105            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3106        }
3107    }
3108
3109    /* clean up at the end */
3110    if (retval) {
3111        if (does_file_exist("/tmp/changed.files")) {
3112            log_to_screen
3113                (_("See /tmp/changed.files for list of files that have changed."));
3114        }
3115        mvaddstr_and_log_it(g_currentY++,
3116                            0,
3117                            _("Run complete. Errors were reported. Please review the logfile."));
3118    } else {
3119        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3120            mvaddstr_and_log_it(g_currentY++,
3121                                0,
3122                                _("Run complete. Please remove floppy/CD/media and reboot."));
3123        } else {
3124            run_program_and_log_output("sync", FALSE);
3125            if (is_this_device_mounted(MNT_CDROM)) {
3126                res =
3127                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
3128            } else {
3129                res = 0;
3130            }
3131
3132            if (!bkpinfo->please_dont_eject) {
3133                res = eject_device("/dev/cdrom");
3134            }
3135            mvaddstr_and_log_it(g_currentY++,
3136                                0,
3137                                _("Run complete. Please remove media and reboot."));
3138        }
3139    }
3140
3141    // g_I_have_just_nuked is set true by nuke_mode() just before it returns
3142    if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3143      mr_msg(1, "post-nuke found; find out whether we should run it...");
3144      if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3145        run_postnuke = TRUE;
3146        mr_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3147      } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3148        run_postnuke = TRUE;
3149        mr_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3150      } else {
3151        run_postnuke = FALSE;
3152        mr_msg(1, "No, will not run post-nuke.");
3153      }
3154    } else {
3155      mr_msg(1, "No post-nuke found.");
3156    }
3157    if (run_postnuke) {
3158      log_to_screen("Running post-nuke...");
3159      if (mount_all_devices(mountlist, TRUE)) {
3160        log_to_screen
3161          ("Unable to re-mount partitions for post-nuke stuff");
3162      } else {
3163        mr_msg(1, "Re-mounted partitions for post-nuke stuff");
3164        mr_asprintf(&tmp, "post-nuke %s %d", bkpinfo->restore_path,
3165            retval);
3166        mr_msg(2, "Calling '%s'", tmp);
3167        if ((res = run_program_and_log_output(tmp, 0))) {
3168          log_OS_error(tmp);
3169        }
3170        mr_free(tmp);
3171        mr_msg(1, "post-nuke returned w/ res=%d", res);
3172      }
3173      unmount_all_devices(mountlist);
3174      log_to_screen("I've finished post-nuking.");
3175    }
3176
3177    unlink("/tmp/mondo-run-prog.tmp");
3178    set_signals(FALSE);
3179    mr_asprintf(&tmp, "rm -Rf %s", bkpinfo->tmpdir);
3180    run_program_and_log_output(tmp, FALSE);
3181    mr_free(tmp);
3182
3183    log_to_screen
3184        (_("Restore log copied to /tmp/mondo-restore.log on your hard disk"));
3185    log_to_screen(_("Mondo-restore is exiting (retval=%d)"), retval);
3186
3187    mr_asprintf(&tmp, "umount %s", bkpinfo->isodir);
3188    run_program_and_log_output(tmp, 5);
3189    mr_free(tmp);
3190
3191    mr_free(mountlist);
3192    mr_free(raidlist);
3193    if (am_I_in_disaster_recovery_mode()) {
3194        run_program_and_log_output("mount / -o remount,rw", 2);
3195    }                           // for b0rken distros
3196    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3197    free_libmondo_global_strings(); // it's fine to have this here :) really :)
3198
3199    unlink("/tmp/filelist.full");
3200    unlink("/tmp/filelist.full.gz");
3201
3202    exit(retval);
3203}
3204
3205/**************************************************************************
3206 *END_MAIN                                                                *
3207 **************************************************************************/
3208
3209
3210/**************************************************************************
3211 *END_MONDO-RESTORE.C                                                     *
3212 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.