source: MondoRescue/branches/stable/mondo/src/mondorestore/mondo-restore.c @ 1166

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

Suppress g_bkpinfo_DONTUSETHIS (Idea from M. Loiseleur)

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