source: trunk/mondo/src/mondorestore/mondo-restore.c @ 900

Last change on this file since 900 was 900, checked in by Bruno Cornec, 14 years ago

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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