source: trunk/mondo/mondo/mondorestore/mondo-restore.c @ 729

Last change on this file since 729 was 689, checked in by bcornec, 14 years ago

Still other memory management improvements ( I hope :-)

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