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

Last change on this file since 688 was 688, checked in by bcornec, 13 years ago

Huge memory management patch.
Still not finished but a lot as been done.
What remains is around some functions returning strings, and some structure members.
(Could not finish due to laptop failure !)

  • Property svn:keywords set to Id
File size: 95.1 KB
Line 
1/***************************************************************************
2 * $Id: mondo-restore.c 688 2006-07-17 13:44:46Z 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 688 2006-07-17 13:44:46Z 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        if (length_of_file(acl_fname) > 0 && find_home_of_exe("setfacl")) {
2052            set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2053        }
2054        if (length_of_file(xattr_fname) > 0
2055            && find_home_of_exe("setfattr")) {
2056            set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2057        }
2058        paranoid_free(acl_fname);
2059        paranoid_free(xattr_fname);
2060    }
2061    paranoid_free(biggies_whose_EXATs_we_should_set);
2062
2063    if (does_file_exist("/PAUSE")) {
2064        popup_and_OK
2065            (_
2066             ("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2067    }
2068    close_progress_form();
2069    if (retval) {
2070        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2071    } else {
2072        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2073    }
2074    return (retval);
2075}
2076/**************************************************************************
2077 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2078 **************************************************************************/
2079
2080
2081/**
2082 * Restore all afioballs from all CDs in the backup.
2083 * The first CD should be inserted (if not, it will be asked for).
2084 * @param bkpinfo The backup information structure. @c backup_media_type is the
2085 * only field used in @e this function.
2086 * @param filelist The node structure containing the list of files to be
2087 * restored. If no file in some particular afioball is in this list, afio will
2088 * still be called for that fileset, but nothing will be written.
2089 * @return 0 for success, or the number of filesets that failed.
2090 */
2091int
2092restore_all_tarballs_from_CD(struct s_bkpinfo *bkpinfo,
2093                             struct s_node *filelist)
2094{
2095    int retval = 0;
2096    int res;
2097    int attempts;
2098    long current_tarball_number = 0;
2099    long max_val;
2100  /**malloc ***/
2101    char *tmp;
2102    char *tmp1;
2103    char *tarball_fname;
2104    char *progress_str;
2105    char *comment;
2106
2107    assert(bkpinfo != NULL);
2108
2109    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2110    log_msg(2,
2111            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2112    if (g_current_media_number != 1) {
2113        log_msg(3, "OK, that's jacked up.");
2114        g_current_media_number = 1;
2115    }
2116    insist_on_this_cd_number(bkpinfo, g_current_media_number);
2117    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2118    max_val = atol(tmp) + 1;
2119    paranoid_free(tmp);
2120
2121    asprintf(&progress_str, _("Restoring from %s #%d"),
2122            media_descriptor_string(bkpinfo->backup_media_type),
2123            g_current_media_number);
2124    log_to_screen(progress_str);
2125    open_progress_form(_("Restoring from archives"),
2126                       _("Restoring data from the archives."),
2127                       _("Please wait. This may take some time."),
2128                       progress_str, max_val);
2129    for (;;) {
2130        insist_on_this_cd_number(bkpinfo, g_current_media_number);
2131        update_progress_form(progress_str);
2132
2133        asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2134                current_tarball_number);
2135        if (!does_file_exist(tarball_fname)) {
2136            paranoid_free(tarball_fname);
2137            asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2138                    current_tarball_number);
2139        }
2140        if (!does_file_exist(tarball_fname)) {
2141            paranoid_free(tarball_fname);
2142            asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2143                    current_tarball_number);
2144        }
2145        if (!does_file_exist(tarball_fname)) {
2146            paranoid_free(tarball_fname);
2147            asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2148                    current_tarball_number);
2149        }
2150        if (!does_file_exist(tarball_fname)) {
2151            paranoid_free(tarball_fname);
2152            asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.",
2153                    current_tarball_number);
2154        }
2155        if (!does_file_exist(tarball_fname)) {
2156            paranoid_free(tarball_fname);
2157            if (current_tarball_number == 0) {
2158                log_to_screen
2159                    (_
2160                     ("No tarballs. Strange. Maybe you only backed up freakin' big files?"));
2161                return (0);
2162            }
2163            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2164                || system("find " MNT_CDROM
2165                          "/archives/slice* > /dev/null 2> /dev/null") ==
2166                0) {
2167                break;
2168            }
2169            g_current_media_number++;
2170            paranoid_free(progress_str);
2171            asprintf(&progress_str, _("Restoring from %s #%d"),
2172                    media_descriptor_string(bkpinfo->backup_media_type),
2173                    g_current_media_number);
2174            log_to_screen(progress_str);
2175        } else {
2176            paranoid_free(progress_str);
2177            asprintf(&progress_str,
2178                    _("Restoring from fileset #%ld on %s #%d"),
2179                    current_tarball_number,
2180                    media_descriptor_string(bkpinfo->backup_media_type),
2181                    g_current_media_number);
2182//    log_msg(3, "progress_str = %s", progress_str);
2183            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2184                 attempts++) {
2185                res =
2186                    restore_a_tarball_from_CD(tarball_fname,
2187                                              current_tarball_number,
2188                                              filelist);
2189            }
2190            if (res) {
2191                asprintf(&tmp1, _("reported errors"));
2192            } else {
2193                asprintf(&tmp1, _("succeeded"));
2194            }
2195            asprintf(&tmp, _("%s #%d, fileset #%ld - restore %s"),
2196                    media_descriptor_string(bkpinfo->backup_media_type),
2197                    g_current_media_number, current_tarball_number,tmp1);
2198            paranoid_free(tmp1);
2199           
2200            if (attempts > 1) {
2201                asprintf(&tmp1, _(" (%d attempts) - review logs"), attempts);
2202            }
2203            asprintf(&comment, "%s%s", tmp, tmp1);
2204            paranoid_free(tmp);
2205            paranoid_free(tmp1);
2206            if (attempts > 1) {
2207                log_to_screen(comment);
2208            }
2209            paranoid_free(comment);
2210
2211            retval += res;
2212            current_tarball_number++;
2213            g_current_progress++;
2214        }
2215        paranoid_free(tarball_fname);
2216    }
2217    paranoid_free(progress_str);
2218    close_progress_form();
2219
2220    if (retval) {
2221        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2222    } else {
2223        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2224    }
2225
2226    return (retval);
2227}
2228
2229/**************************************************************************
2230 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2231 **************************************************************************/
2232
2233
2234/**
2235 * Restore all biggiefiles from the currently opened stream.
2236 * @param bkpinfo The backup information structure. Passed to other functions.
2237 * @param filelist The node structure containing the list of files to be
2238 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2239 * @return 0 for success, or the number of biggiefiles that failed.
2240 */
2241int
2242restore_all_biggiefiles_from_stream(struct s_bkpinfo *bkpinfo,
2243                                    struct s_node *filelist)
2244{
2245    long noof_biggiefiles;
2246    long current_bigfile_number = 0;
2247    long total_slices;
2248
2249    int retval = 0;
2250    int res = 0;
2251    int ctrl_chr;
2252
2253  /** malloc add ****/
2254    char *tmp = NULL;
2255    char *biggie_fname = NULL;
2256    char *xattr_fname = NULL;
2257    char *acl_fname = NULL;
2258    char *p = NULL;
2259    char *pathname_of_last_biggie_restored = NULL;
2260    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
2261    long long biggie_size = NULL;
2262    FILE *fbw = NULL;
2263
2264    assert(bkpinfo != NULL);
2265
2266    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2267    total_slices = atol(tmp);
2268    paranoid_free(tmp);
2269
2270    asprintf(&tmp, "Reassembling large files      ");
2271    asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2272    asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2273    mvaddstr_and_log_it(g_currentY, 0, tmp);
2274    paranoid_free(tmp);
2275
2276    asprintf(&biggies_whose_EXATs_we_should_set,
2277            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2278    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2279        log_msg(1, "Warning - cannot openout %s",
2280                biggies_whose_EXATs_we_should_set);
2281    }
2282// get xattr and acl files if they're there
2283    res =
2284        read_header_block_from_stream(&biggie_size, biggie_fname,
2285                                      &ctrl_chr);
2286    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2287        res =
2288            read_EXAT_files_from_tape(bkpinfo, &biggie_size, biggie_fname,
2289                                      &ctrl_chr, xattr_fname, acl_fname);
2290    }
2291
2292    noof_biggiefiles = atol(biggie_fname);
2293    asprintf(&tmp, "OK, there are %ld biggiefiles in the archives",
2294            noof_biggiefiles);
2295    log_msg(2, tmp);
2296    paranoid_free(tmp);
2297
2298    open_progress_form(_("Reassembling large files"),
2299                       _("I am now reassembling all the large files."),
2300                       _("Please wait. This may take some time."),
2301                       "", total_slices);
2302
2303    for (res =
2304         read_header_block_from_stream(&biggie_size, biggie_fname,
2305                                       &ctrl_chr);
2306         ctrl_chr != BLK_STOP_BIGGIEFILES;
2307         res =
2308         read_header_block_from_stream(&biggie_size, biggie_fname,
2309                                       &ctrl_chr)) {
2310        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2311            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2312            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2313        }
2314        /* BERLIOS: useless
2315        p = strrchr(biggie_fname, '/');
2316        if (!p) {
2317            p = biggie_fname;
2318        } else {
2319            p++;
2320        }
2321        */
2322        asprintf(&tmp, _("Restoring big file %ld (%lld K)"),
2323                current_bigfile_number + 1, biggie_size / 1024);
2324        update_progress_form(tmp);
2325        paranoid_free(tmp);
2326
2327        pathname_of_last_biggie_restored = restore_a_biggiefile_from_stream(bkpinfo, biggie_fname,
2328                                               current_bigfile_number,
2329                                               filelist, ctrl_chr);
2330        log_msg(1, "I believe I have restored %s",
2331                pathname_of_last_biggie_restored);
2332        if (fbw && pathname_of_last_biggie_restored[0]) {
2333            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2334        }
2335        paranoid_free(pathname_of_last_biggie_restored);
2336
2337        retval += res;
2338        current_bigfile_number++;
2339
2340    }
2341    if (current_bigfile_number != noof_biggiefiles
2342        && noof_biggiefiles != 0) {
2343        asprintf(&tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2344                current_bigfile_number, noof_biggiefiles);
2345    } else {
2346        asprintf(&tmp,
2347                "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2348                noof_biggiefiles, current_bigfile_number);
2349    }
2350    log_msg(1, tmp);
2351    paranoid_free(tmp);
2352
2353    if (fbw) {
2354        fclose(fbw);
2355        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2356            iamhere("Setting biggie-EXATs");
2357            if (length_of_file(acl_fname) > 0) {
2358                log_msg(1, "set_acl_list(%s,%s)",
2359                        biggies_whose_EXATs_we_should_set, acl_fname);
2360                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2361            }
2362            if (length_of_file(xattr_fname) > 0) {
2363                log_msg(1, "set_fattr_List(%s,%s)",
2364                        biggies_whose_EXATs_we_should_set, xattr_fname);
2365                set_fattr_list(biggies_whose_EXATs_we_should_set,
2366                               xattr_fname);
2367            }
2368        } else {
2369            iamhere
2370                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2371        }
2372    }
2373    paranoid_free(xattr_fname);
2374    paranoid_free(acl_fname);
2375    paranoid_free(biggies_whose_EXATs_we_should_set);
2376
2377    if (does_file_exist("/PAUSE")) {
2378        popup_and_OK
2379            (_
2380             ("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2381    }
2382
2383    close_progress_form();
2384    if (retval) {
2385        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2386    } else {
2387        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2388    }
2389    paranoid_free(biggie_fname);
2390    return (retval);
2391}
2392
2393/**************************************************************************
2394 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2395 **************************************************************************/
2396
2397
2398/**
2399 * Restore all afioballs from the currently opened tape stream.
2400 * @param bkpinfo The backup information structure. Fields used:
2401 * - @c bkpinfo->backup_media_type
2402 * - @c bkpinfo->restore_path
2403 * @param filelist The node structure containing the list of files to be
2404 * restored. If no file in an afioball is in this list, afio will still be
2405 * called for that fileset, but nothing will be written.
2406 * @return 0 for success, or the number of filesets that failed.
2407 */
2408int
2409restore_all_tarballs_from_stream(struct s_bkpinfo *bkpinfo,
2410                                 struct s_node *filelist)
2411{
2412    int retval = 0;
2413    int res;
2414    long current_afioball_number = 0;
2415    int ctrl_chr;
2416    long max_val /*, total_noof_files */ ;
2417
2418  /** malloc **/
2419    char *tmp = NULL;
2420    char *progress_str = NULL;
2421    char *tmp_fname = NULL;
2422    char *xattr_fname = NULL;
2423    char *acl_fname = NULL;
2424
2425    long long tmp_size;
2426
2427    assert(bkpinfo != NULL);
2428    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2429    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2430    max_val = atol(tmp) + 1;
2431    paranoid_free(tmp);
2432
2433    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2434
2435    run_program_and_log_output("pwd", 5);
2436
2437    asprintf(&progress_str, _("Restoring from media #%d"),
2438            g_current_media_number);
2439    log_to_screen(progress_str);
2440    open_progress_form(_("Restoring from archives"),
2441                       _("Restoring data from the archives."),
2442                       _("Please wait. This may take some time."),
2443                       progress_str, max_val);
2444
2445    log_msg(3, "hey");
2446
2447    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2448    if (res) {
2449        log_msg(2, "Warning - error reading afioball from tape");
2450    }
2451    retval += res;
2452    if (ctrl_chr != BLK_START_AFIOBALLS) {
2453        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2454    }
2455    log_msg(2, "ho");
2456    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2457    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2458        update_progress_form(progress_str);
2459        asprintf(&xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2460                current_afioball_number);
2461        asprintf(&acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2462                current_afioball_number);
2463        unlink(xattr_fname);
2464        unlink(acl_fname);
2465        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2466            iamhere("Reading EXAT files from tape");
2467            res =
2468                read_EXAT_files_from_tape(bkpinfo, &tmp_size, tmp_fname,
2469                                          &ctrl_chr, xattr_fname,
2470                                          acl_fname);
2471        }
2472        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2473            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2474        }
2475        /* BERLIOS: useless ?
2476        asprintf(&tmp,
2477                _("Restoring from fileset #%ld (name=%s, size=%ld K)"),
2478                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2479                */
2480        res =
2481            restore_a_tarball_from_stream(bkpinfo, tmp_fname,
2482                                          current_afioball_number,
2483                                          filelist, tmp_size, xattr_fname,
2484                                          acl_fname);
2485        retval += res;
2486        if (res) {
2487            asprintf(&tmp, _("Fileset %ld - errors occurred"),
2488                    current_afioball_number);
2489            log_to_screen(tmp);
2490            paranoid_free(tmp);
2491        }
2492        res =
2493            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2494        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2495            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2496        }
2497
2498        current_afioball_number++;
2499        g_current_progress++;
2500
2501        paranoid_free(progress_str);
2502        asprintf(&progress_str, _("Restoring from fileset #%ld on %s #%d"),
2503                current_afioball_number,
2504                media_descriptor_string(bkpinfo->backup_media_type),
2505                g_current_media_number);
2506        res =
2507            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2508        unlink(xattr_fname);
2509        unlink(acl_fname);
2510        paranoid_free(xattr_fname);
2511        paranoid_free(acl_fname);
2512    }                           // next
2513    paranoid_free(progress_str);
2514    paranoid_free(tmp_fname);
2515
2516    log_msg(1, "All done with afioballs");
2517    close_progress_form();
2518    if (retval) {
2519        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2520    } else {
2521        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2522    }
2523    return (retval);
2524}
2525
2526/**************************************************************************
2527 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2528 **************************************************************************/
2529
2530/* @} - end of LLrestoreGroup */
2531
2532
2533/**
2534 * Restore all files in @p filelist.
2535 * @param bkpinfo The backup information structure. Most fields are used.
2536 * @param filelist The node structure containing the list of files to be
2537 * restored.
2538 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2539 * @ingroup restoreGroup
2540 */
2541int restore_everything(struct s_bkpinfo *bkpinfo, struct s_node *filelist)
2542{
2543    int resA;
2544    int resB;
2545
2546  /** mallco ***/
2547    char *cwd = NULL;
2548    char *newpath = NULL;
2549    char *tmp = NULL;
2550    assert(bkpinfo != NULL);
2551
2552    malloc_string(cwd);
2553    malloc_string(newpath);
2554    log_msg(2, "restore_everything() --- starting");
2555    g_current_media_number = 1;
2556    /* BERLIOS: should test return value, or better change the function */
2557    getcwd(cwd, MAX_STR_LEN - 1);
2558    asprintf(&tmp, "mkdir -p %s", bkpinfo->restore_path);
2559    run_program_and_log_output(tmp, FALSE);
2560    paranoid_free(tmp);
2561
2562    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2563    chdir(bkpinfo->restore_path);
2564    /* BERLIOS: should test return value, or better change the function */
2565    getcwd(newpath, MAX_STR_LEN - 1);
2566    log_msg(1, "path is now %s", newpath);
2567    log_msg(1, "restoring everything");
2568    if (!find_home_of_exe("petris") && !g_text_mode) {
2569        newtDrawRootText(0, g_noof_rows - 2,
2570                         _
2571                         ("Press ALT-<left cursor> twice to play Petris :-) "));
2572        newtRefresh();
2573    }
2574    mvaddstr_and_log_it(g_currentY, 0,
2575                        _("Preparing to read your archives"));
2576    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2577        mount_cdrom(bkpinfo);
2578        mvaddstr_and_log_it(g_currentY++, 0,
2579                            _
2580                            ("Restoring OS and data from streaming media"));
2581        if (bkpinfo->backup_media_type == cdstream) {
2582            openin_cdstream(bkpinfo);
2583        } else {
2584            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->
2585                                                         media_device);
2586            openin_tape(bkpinfo);
2587        }
2588        resA = restore_all_tarballs_from_stream(bkpinfo, filelist);
2589        resB = restore_all_biggiefiles_from_stream(bkpinfo, filelist);
2590        if (bkpinfo->backup_media_type == cdstream) {
2591            closein_cdstream(bkpinfo);
2592        } else {
2593            closein_tape(bkpinfo);
2594        }
2595    } else {
2596        mvaddstr_and_log_it(g_currentY++, 0,
2597                            _("Restoring OS and data from CD       "));
2598        mount_cdrom(bkpinfo);
2599        resA = restore_all_tarballs_from_CD(bkpinfo, filelist);
2600        resB = restore_all_biggiefiles_from_CD(bkpinfo, filelist);
2601    }
2602    chdir(cwd);
2603    if (resA + resB) {
2604        log_to_screen(_("Errors occurred while data was being restored."));
2605    }
2606    if (length_of_file("/etc/raidtab") > 0) {
2607        log_msg(2, "Copying local raidtab to restored filesystem");
2608        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2609                                   "/etc/raidtab", FALSE);
2610    }
2611    kill_petris();
2612    log_msg(2, "restore_everything() --- leaving");
2613    paranoid_free(cwd);
2614    paranoid_free(newpath);
2615    return (resA + resB);
2616}
2617
2618/**************************************************************************
2619 *END_RESTORE_EVERYTHING                                                  *
2620 **************************************************************************/
2621
2622
2623extern void wait_until_software_raids_are_prepped(char *, int);
2624
2625char which_restore_mode(void);
2626
2627
2628/**
2629 * Log a "don't panic" message to the logfile.
2630 */
2631void welcome_to_mondorestore()
2632{
2633    log_msg(0, "-------------- Mondo Restore v%s -------------",
2634            PACKAGE_VERSION);
2635    log_msg(0,
2636            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2637    log_msg(0,
2638            "don't break out in a cold sweat just because you see a few  ");
2639    log_msg(0,
2640            "error messages in the log. Read them; analyze them; see if  ");
2641    log_msg(0,
2642            "they are significant; above all, verify your backups! Please");
2643    log_msg(0,
2644            "attach a compressed copy of this log to any e-mail you send ");
2645    log_msg(0,
2646            "to the Mondo mailing list when you are seeking technical    ");
2647    log_msg(0,
2648            "support. Without it, we can't help you.            - DevTeam");
2649    log_msg(0,
2650            "------------------------------------------------------------");
2651    log_msg(0,
2652            "BTW, despite (or perhaps because of) the wealth of messages,");
2653    log_msg(0,
2654            "some users are inclined to stop reading this log.  If Mondo ");
2655    log_msg(0,
2656            "stopped for some reason, chances are it's detailed here.    ");
2657    log_msg(0,
2658            "More than likely there's a message near the end of this     ");
2659    log_msg(0,
2660            "log that will tell you what is wrong.  Please read it!      ");
2661    log_msg(0,
2662            "------------------------------------------------------------");
2663}
2664
2665
2666/**
2667 * Restore the user's data.
2668 * What did you think it did, anyway? :-)
2669 */
2670int main(int argc, char *argv[])
2671{
2672    FILE *fin = NULL;
2673    FILE *fout = NULL;
2674    int retval = 0;
2675    int res = 0;
2676    char *tmp = NULL;
2677
2678    struct mountlist_itself *mountlist = NULL;
2679    struct raidlist_itself *raidlist = NULL;
2680    struct s_bkpinfo *bkpinfo = NULL;
2681    struct s_node *filelist = NULL;
2682    char *a = NULL, *b = NULL;
2683
2684  /**************************************************************************
2685   * hugo-                                                                  *
2686   * busy stuff here - it needs some comments -stan                           *
2687   *                                                                        *
2688   **************************************************************************/
2689
2690#ifdef ENABLE_NLS
2691    setlocale(LC_ALL, "");
2692    (void) textdomain("mondo");
2693#endif
2694
2695    if (getuid() != 0) {
2696        fprintf(stderr, _("Please run as root.\n"));
2697        exit(127);
2698    }
2699
2700    g_loglevel = DEFAULT_MR_LOGLEVEL;
2701
2702/* Configure global variables */
2703#ifdef __FreeBSD__
2704    tmp = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
2705#else
2706    tmp = call_program_and_get_last_line_of_output("cat /proc/cmdline");
2707#endif
2708    if (strstr(tmp,"textonly")) {
2709        g_text_mode = TRUE;
2710        log_msg(1, "TEXTONLY MODE");
2711    } else {
2712        g_text_mode = FALSE;
2713    }                           // newt :-)
2714    paranoid_free(tmp);
2715
2716    if (!
2717        (bkpinfo = g_bkpinfo_DONTUSETHIS =
2718         malloc(sizeof(struct s_bkpinfo)))) {
2719        fatal_error("Cannot malloc bkpinfo");
2720    }
2721    if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
2722        fatal_error("Cannot malloc mountlist");
2723    }
2724    if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
2725        fatal_error("Cannot malloc raidlist");
2726    }
2727
2728    malloc_libmondo_global_strings();
2729
2730    g_mondo_home = call_program_and_get_last_line_of_output("which mondorestore"));
2731    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2732    make_hole_for_dir(g_tmpfs_mountpt);
2733    g_current_media_number = 1; // precaution
2734
2735    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2736    run_program_and_log_output("mkdir -p /mnt/floppy", FALSE);
2737
2738    setup_MR_global_filenames(bkpinfo); // malloc() and set globals, using bkpinfo->tmpdir etc.
2739    reset_bkpinfo(bkpinfo);
2740    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2741    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2742    if (am_I_in_disaster_recovery_mode()) {
2743        run_program_and_log_output("mount / -o remount,rw", 2);
2744    }                           // for b0rken distros
2745    g_main_pid = getpid();
2746    srandom((int) (time(NULL)));
2747    register_pid(getpid(), "mondo");
2748    set_signals(TRUE);
2749    g_kernel_version = get_kernel_version();
2750
2751    log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2752    if (strlen(g_mountlist_fname) < 3) {
2753        fatal_error
2754            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2755    }
2756    mkdir(MNT_CDROM, 0x770);
2757
2758/* Backup original mountlist.txt */
2759    asprintf(&tmp, "%s.orig", g_mountlist_fname);
2760    if (!does_file_exist(g_mountlist_fname)) {
2761        log_msg(2,
2762                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2763                __LINE__, g_mountlist_fname);
2764    } else if (!does_file_exist(tmp)) {
2765        paranoid_free(tmp);
2766        asprintf(&tmp, "cp -f %s %s.orig", g_mountlist_fname,
2767                g_mountlist_fname);
2768        run_program_and_log_output(tmp, FALSE);
2769    }
2770    paranoid_free(tmp);
2771
2772/* Init directories */
2773    make_hole_for_dir(bkpinfo->tmpdir);
2774    asprintf(&tmp, "mkdir -p %s", bkpinfo->tmpdir);
2775    run_program_and_log_output(tmp, FALSE);
2776    paranoid_free(tmp);
2777
2778    make_hole_for_dir("/var/log");
2779    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
2780    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2781    run_program_and_log_output
2782        ("ln -sf " MONDO_LOGFILE " /tmp/mondo-restore.log", FALSE);
2783
2784    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2785
2786/* Init GUI */
2787    malloc_libmondo_global_strings();
2788    setup_newt_stuff();         /* call newtInit and setup screen log */
2789    welcome_to_mondorestore();
2790    if (bkpinfo->disaster_recovery) {
2791        log_msg(1, "I am in disaster recovery mode");
2792    } else {
2793        log_msg(1, "I am in normal, live mode");
2794    }
2795
2796    iamhere("what time is it");
2797
2798/* Process command-line parameters */
2799    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
2800#ifdef __FreeBSD__
2801        system("mv -f /tmp/raidconf.txt /etc/raidtab");
2802        if (!does_file_exist("/etc/raidtab"))
2803            system("vinum printconfig > /etc/raidtab");
2804#endif
2805        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2806        if (!does_file_exist(g_mountlist_fname)) {
2807            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2808        }
2809        res = let_user_edit_the_mountlist(bkpinfo, mountlist, raidlist);
2810#ifdef __FreeBSD__
2811        system("mv -f /etc/raidtab /tmp/raidconf.txt");
2812#endif
2813        paranoid_MR_finish(res);
2814    }
2815
2816    g_loglevel = DEFAULT_MR_LOGLEVEL;
2817    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
2818        fout = fopen("/tmp/out.txt", "w");
2819        fput_string_one_char_at_a_time(stderr, argv[2]);
2820        finish(0);
2821    }
2822
2823    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
2824        make_grub_install_scriptlet(argv[2]);
2825        finish(0);
2826    }
2827
2828    if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
2829        if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
2830            system("mount " MNT_CDROM);
2831        }
2832        bkpinfo->compression_level = 1;
2833        g_current_media_number = 2;
2834        strcpy(bkpinfo->restore_path, "/tmp/TESTING");
2835        bkpinfo->backup_media_type = dvd;
2836        open_progress_form(_("Reassembling /dev/hda1"),
2837                           _("Shark is a bit of a silly person."),
2838                           _("Please wait. This may take some time."),
2839                           "", 1999);
2840        system("rm -Rf /tmp/*pih*");
2841
2842        (void)restore_a_biggiefile_from_CD(bkpinfo, 42, NULL);
2843    }
2844
2845    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
2846        g_loglevel = 6;
2847        filelist = load_filelist(argv[2]);
2848        if (!filelist) {
2849            fatal_error("Failed to load filelist");
2850        }
2851        toggle_node_selection(filelist, FALSE);
2852        toggle_all_root_dirs_on(filelist);
2853        // BERLIOS: /usr/lib ???
2854        toggle_path_selection(filelist, "/usr/share", TRUE);
2855//      show_filelist(filelist);
2856        save_filelist(filelist, "/tmp/out.txt");
2857//      finish(0);
2858//      toggle_path_selection (filelist, "/root/stuff", TRUE);
2859        asprintf(&a, argv[3]);
2860        asprintf(&b, argv[4]);
2861
2862        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
2863        free_filelist(filelist);
2864        paranoid_free(a);
2865        paranoid_free(b);
2866        printf("res = %d", res);
2867        finish(0);
2868    }
2869
2870    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
2871        popup_changelist_from_file(argv[2]);
2872        paranoid_MR_finish(0);
2873    }
2874
2875    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
2876        log_msg(1, "SCORE");
2877        g_loglevel = 10;
2878        if (strstr(argv[2], "save")) {
2879            log_msg(1, "Saving from %s to %s", argv[3], argv[4]);
2880            fin = fopen(argv[3], "r");
2881            fout = fopen(argv[4], "w");
2882            copy_from_src_to_dest(fin, fout, 'w');
2883            fclose(fin);
2884            fin = fopen(argv[3], "r");
2885            copy_from_src_to_dest(fin, fout, 'w');
2886            fclose(fout);
2887            fclose(fin);
2888        } else if (strstr(argv[2], "restore")) {
2889            fout = fopen(argv[3], "w");
2890            fin = fopen(argv[4], "r");
2891            copy_from_src_to_dest(fout, fin, 'r');
2892            fclose(fin);
2893            fin = fopen(argv[4], "r");
2894            copy_from_src_to_dest(fout, fin, 'r');
2895            fclose(fout);
2896            fclose(fin);
2897        } else {
2898            fatal_error("Unknown additional param");
2899        }
2900        finish(0);
2901    }
2902
2903    if (argc == 3 && strcmp(argv[1], "--mdstat") == 0) {
2904        wait_until_software_raids_are_prepped(argv[2], 100);
2905        finish(0);
2906    }
2907
2908    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
2909        finish(create_raidtab_from_mdstat(argv[2]));
2910    }
2911
2912
2913    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
2914        retval = run_grub(FALSE, "/dev/hda");
2915        if (retval) {
2916            log_to_screen(_("Failed to write Master Boot Record"));
2917        }
2918        paranoid_MR_finish(0);
2919    }
2920    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
2921        g_current_media_number = atoi(argv[2]);
2922        pause_and_ask_for_cdr(5, NULL);
2923        paranoid_MR_finish(0);
2924    } else if (!bkpinfo->disaster_recovery) {   // live!
2925        if (argc != 1) {
2926            popup_and_OK
2927                (_
2928                 ("Live mode doesn't support command-line parameters yet."));
2929            paranoid_MR_finish(1);
2930//    return(1);
2931        }
2932        log_msg(1, "I am in normal, live mode.");
2933        log_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
2934        mount_boot_if_necessary();  /* for Gentoo users */
2935        log_msg(2, "Still here.");
2936        if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
2937            g_restoring_live_from_cd = TRUE;
2938        } else {
2939            log_msg(2, "Calling restore_to_live_filesystem()");
2940            retval = restore_to_live_filesystem(bkpinfo);
2941        }
2942        log_msg(2, "Still here. Yay.");
2943        if (strlen(bkpinfo->tmpdir) > 0) {
2944            asprintf(&tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
2945            run_program_and_log_output(tmp, FALSE);
2946            paranoid_free(tmp);
2947        }
2948        unmount_boot_if_necessary();    /* for Gentoo users */
2949        paranoid_MR_finish(retval);
2950    } else {
2951/* Disaster recovery mode (must be) */
2952        log_msg(1, "I must be in disaster recovery mode.");
2953        log_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
2954        if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
2955            log_to_screen(_("Uh, that hasn't been implemented yet."));
2956            paranoid_MR_finish(1);
2957        }
2958
2959        iamhere("About to call load_mountlist and load_raidtab");
2960        strcpy(bkpinfo->restore_path, MNT_RESTORING);
2961        read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
2962        retval = load_mountlist(mountlist, g_mountlist_fname);
2963        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2964        iamhere
2965            ("Returned from calling load_mountlist and load_raidtab successfully");
2966
2967        if (argc > 1
2968            && (strcmp(argv[1], "--compare") == 0
2969                || strcmp(argv[1], "--nuke") == 0)) {
2970            if (bkpinfo->backup_media_type == nfs
2971                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
2972                log_msg(1, "Mounting nfs dir");
2973                sprintf(bkpinfo->isodir, "/tmp/isodir");
2974                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
2975                asprintf(&tmp, "mount %s -t nfs -o nolock /tmp/isodir",
2976                        bkpinfo->nfs_mount);
2977                run_program_and_log_output(tmp, 1);
2978                paranoid_free(tmp);
2979            }
2980        }
2981
2982
2983        if (retval) {
2984            log_to_screen
2985                (_
2986                 ("Warning - load_raidtab_into_raidlist returned an error"));
2987        }
2988
2989
2990        log_msg(1, "Send in the clowns.");
2991
2992        if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
2993            log_msg(0, "Partitioning only.");
2994            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2995            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2996            load_mountlist(mountlist, g_mountlist_fname);
2997            res = partition_everything(mountlist);
2998            finish(res);
2999        }
3000
3001        if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3002            log_msg(0, "Formatting only.");
3003            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3004            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3005            load_mountlist(mountlist, g_mountlist_fname);
3006            res = format_everything(mountlist, FALSE, raidlist);
3007            finish(res);
3008        }
3009
3010        if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3011            log_msg(0, "Stopping LVM and RAID");
3012            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3013            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3014            load_mountlist(mountlist, g_mountlist_fname);
3015            res = do_my_funky_lvm_stuff(TRUE, FALSE);
3016            res += stop_all_raid_devices(mountlist);
3017            finish(res);
3018        }
3019
3020        if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3021            iamhere("nuking");
3022            retval += nuke_mode(bkpinfo, mountlist, raidlist);
3023        } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3024            iamhere("catchall");
3025            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3026        } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3027            iamhere("compare");
3028            retval += compare_mode(bkpinfo, mountlist, raidlist);
3029        } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3030            iamhere("iso");
3031            retval = iso_mode(bkpinfo, mountlist, raidlist, FALSE);
3032        } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3033            iamhere("mbr");
3034            retval = mount_all_devices(mountlist, TRUE);
3035            if (!retval) {
3036                retval += run_boot_loader(FALSE);
3037                retval += unmount_all_devices(mountlist);
3038            }
3039            if (retval) {
3040                log_to_screen(_("Failed to write Master Boot Record"));
3041            }
3042        } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3043            iamhere("isonuke");
3044            retval = iso_mode(bkpinfo, mountlist, raidlist, TRUE);
3045        } else if (argc != 1) {
3046            log_to_screen(_("Invalid paremeters"));
3047            paranoid_MR_finish(1);
3048        } else {
3049            iamhere("catchall (no mode specified in command-line call");
3050            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3051        }
3052    }
3053
3054    /* clean up at the end */
3055    if (retval) {
3056        if (does_file_exist("/tmp/changed.files")) {
3057            log_to_screen
3058                (_
3059                 ("See /tmp/changed.files for list of files that have changed."));
3060        }
3061        mvaddstr_and_log_it(g_currentY++,
3062                            0,
3063                            _
3064                            ("Run complete. Errors were reported. Please review the logfile."));
3065    } else {
3066        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3067            mvaddstr_and_log_it(g_currentY++,
3068                                0,
3069                                _
3070                                ("Run complete. Please remove floppy/CD/media and reboot."));
3071        } else {
3072            run_program_and_log_output("sync", FALSE);
3073            if (is_this_device_mounted(MNT_CDROM)) {
3074                res =
3075                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
3076            } else {
3077                res = 0;
3078            }
3079
3080            if (!bkpinfo->please_dont_eject) {
3081                res = eject_device("/dev/cdrom");
3082/*
3083              if (res)
3084        {
3085          log_to_screen( "WARNING - failed to eject CD-ROM disk" );
3086        }
3087*/
3088            }
3089            mvaddstr_and_log_it(g_currentY++,
3090                                0,
3091                                _
3092                                ("Run complete. Please remove media and reboot."));
3093        }
3094    }
3095
3096// g_I_have_just_nuked is set true by nuke_mode() just before it returns
3097    if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3098        if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3099            log_msg(1, "post-nuke found; running...");
3100            if (mount_all_devices(mountlist, TRUE)) {
3101                log_to_screen
3102                    (_
3103                     ("Unable to re-mount partitions for post-nuke stuff"));
3104            } else {
3105                log_msg(1, "Re-mounted partitions for post-nuke stuff");
3106                asprintf(&tmp, "post-nuke %s %d", bkpinfo->restore_path,
3107                        retval);
3108                if (!g_text_mode) {
3109                    newtSuspend();
3110                }
3111                log_msg(2, "Calling '%s'", tmp);
3112                if ((res = system(tmp))) {
3113                    log_OS_error(tmp);
3114                }
3115                paranoid_free(tmp);
3116                if (!g_text_mode) {
3117                    newtResume();
3118                }
3119//              newtCls();
3120                log_msg(1, "post-nuke returned w/ res=%d", res);
3121            }
3122            unmount_all_devices(mountlist);
3123            log_msg(1, "I've finished post-nuking.");
3124        }
3125    }
3126/* 
3127  log_to_screen("If you are REALLY in a hurry, hit Ctrl-Alt-Del now.");
3128  log_to_screen("Otherwise, please wait until the RAID disks are done.");
3129  wait_until_software_raids_are_prepped("/proc/mdstat", 100);
3130  log_to_screen("Thank you.");
3131*/
3132    unlink("/tmp/mondo-run-prog.tmp");
3133    set_signals(FALSE);
3134    asprintf(&tmp, "rm -Rf %s", bkpinfo->tmpdir);
3135    run_program_and_log_output(tmp, FALSE);
3136    paranoid_free(tmp);
3137
3138    log_to_screen
3139        (_
3140         ("Restore log copied to /tmp/mondo-restore.log on your hard disk"));
3141    asprintf(&tmp,
3142            _
3143            ("Mondo-restore is exiting (retval=%d)                                      "),
3144            retval);
3145    log_to_screen(tmp);
3146    paranoid_free(tmp);
3147
3148    asprintf(&tmp, "umount %s", bkpinfo->isodir);
3149    run_program_and_log_output(tmp, 5);
3150    paranoid_free(tmp);
3151
3152    paranoid_free(mountlist);
3153    paranoid_free(raidlist);
3154    if (am_I_in_disaster_recovery_mode()) {
3155        run_program_and_log_output("mount / -o remount,rw", 2);
3156    }                           // for b0rken distros
3157    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3158    free_libmondo_global_strings(); // it's fine to have this here :) really :)
3159
3160    unlink("/tmp/filelist.full");
3161    unlink("/tmp/filelist.full.gz");
3162
3163    exit(retval);
3164}
3165
3166/**************************************************************************
3167 *END_MAIN                                                                *
3168 **************************************************************************/
3169
3170
3171/**************************************************************************
3172 *END_MONDO-RESTORE.C                                                     *
3173 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.