source: branches/2.2.9/mondo/src/mondorestore/mondorestore.c @ 2381

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

Fix a missing param for sshfs call

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