source: branches/2.2.10/mondo/src/mondorestore/mondorestore.c @ 2383

Last change on this file since 2383 was 2383, checked in by Bruno Cornec, 11 years ago

call_program_and_get_last_line_of_output is now allocating memory and returning that string

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