source: MondoRescue/branches/stable/mondo/src/mondorestore/mondorestore.c @ 1203

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

Still searching

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