source: branches/3.2/mondo/src/mondorestore/mondorestore.c @ 3263

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