source: branches/stable/mondo/src/mondorestore/mondorestore.c @ 1621

Last change on this file since 1621 was 1621, checked in by bruno, 12 years ago

(merge -r1599:1614 $SVN_M/branches/2.2.5 .)

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