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

Last change on this file since 1193 was 1193, checked in by bruno, 13 years ago

Remove some useless \r in code
Remove center_string usage as it's now broiken for dynamically created strings

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