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

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

Use of conf file entries (iso_burning_*, media_device, media_size)
and adapatation of the rest of the code to that (including bkpinfo)

  • Property svn:keywords set to Id
File size: 98.4 KB
Line 
1/***************************************************************************
2* restores mondoarchive data
3* $Id: mondorestore.c 1594 2007-08-26 10:26:06Z 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 1594 2007-08-26 10:26:06Z 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            (strstr(tmp1,"RESTORE") == NULL)) {
716            /* -H option */
717            mr_asprintf(&tmp,
718                _(" 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."));
719            popup_and_OK(tmp);
720            mr_free(tmp);
721        }
722
723        log_to_screen(_("Mondo has restored your system. Please remove the backup media and reboot."));
724        log_to_screen(_("Thank you for using Mondo Rescue."));
725        log_to_screen(_("Please visit our website at http://www.mondorescue.org for more information."));
726    }
727    g_I_have_just_nuked = TRUE;
728    return;
729}
730
731
732/**
733 * Restore the user's data automatically (no prompts), after a twenty-second
734 * warning period.
735 * @param bkpinfo The backup information structure. Most fields are used.
736 * @param mountlist The mountlist containing information about the user's partitions.
737 * @param raidlist The raidlist that goes with @p mountlist.
738 * @return 0 for success, or the number of errors encountered.
739 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
740 */
741int
742nuke_mode(struct s_bkpinfo *bkpinfo,
743          struct mountlist_itself *mountlist,
744          struct raidlist_itself *raidlist)
745{
746    int retval = 0;
747    int res = 0;
748    bool boot_loader_installed = FALSE;
749    char *tmp = NULL;
750    char tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
751        tmpC[MAX_STR_LEN];
752
753    assert(bkpinfo != NULL);
754    assert(mountlist != NULL);
755    assert(raidlist != NULL);
756
757    mr_msg(2, "nuke_mode --- starting");
758
759    get_cfg_file_from_archive_or_bust(bkpinfo);
760    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo updated the mountlist
761#ifdef __FreeBSD__
762    tmp = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
763#else
764    tmp = call_program_and_get_last_line_of_output("cat /proc/cmdline");
765#endif
766    if (strstr(tmp,"noresize")) {
767        mr_msg(2, "Not resizing mountlist.");
768    } else {
769        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
770    }
771    if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
772        mr_asprintf(&tmp,
773                _("Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?"),
774                tmpA, tmpB, tmpC);
775        if (ask_me_yes_or_no(tmp)) {
776            mr_free(tmp);
777            retval = interactive_mode(bkpinfo, mountlist, raidlist);
778            call_me_after_the_nuke(retval);
779            return(retval);
780        } else {
781            mr_free(tmp);
782            fatal_error("Nuke Mode aborted. ");
783        }
784    }
785    save_mountlist_to_disk(mountlist, g_mountlist_fname);
786    mvaddstr_and_log_it(1, 30, _("Restoring Automatically"));
787    if (bkpinfo->differential) {
788        log_to_screen(_("Because this is a differential backup, disk"));
789        log_to_screen(_("partitioning and formatting will not take place."));
790        res = 0;
791    } else {
792        if (partition_table_contains_Compaq_diagnostic_partition
793            (mountlist)) {
794            offer_to_abort_because_Compaq_Proliants_suck();
795        } else {
796            twenty_seconds_til_yikes();
797            g_fprep = fopen("/tmp/prep.sh", "w");
798#ifdef __FreeBSD__
799            tmp = call_program_and_get_last_line_of_output("cat /tmp/cmdline");
800#else
801            tmp = call_program_and_get_last_line_of_output("cat /proc/cmdline");
802#endif
803            if (strstr(tmp,"nopart")) {
804                mr_msg(2,
805                        "Not partitioning drives due to 'nopart' option.");
806                res = 0;
807            } else {
808                res = partition_everything(mountlist);
809                if (res) {
810                    log_to_screen
811                        (_("Warning. Errors occurred during partitioning."));
812                    res = 0;
813                }
814            }
815            retval += res;
816            if (!res) {
817                log_to_screen(_("Preparing to format your disk(s)"));
818                sleep(1);
819                sync();
820                log_to_screen(_("Please wait. This may take a few minutes."));
821                res += format_everything(mountlist, FALSE, raidlist);
822            }
823            paranoid_fclose(g_fprep);
824        }
825    }
826    retval += res;
827    if (res) {
828        mvaddstr_and_log_it(g_currentY++,
829                            0,
830                            _("Failed to partition and/or format your hard drives."));
831
832        if (ask_me_yes_or_no(_("Try in interactive mode instead?"))) {
833            retval = interactive_mode(bkpinfo, mountlist, raidlist);
834            call_me_after_the_nuke(retval);
835            return(retval);
836        } else
837            if (!ask_me_yes_or_no
838                (_("Would you like to try to proceed anyway?"))) {
839                return(retval);
840        }
841    }
842    retval = mount_all_devices(mountlist, TRUE);
843    if (retval) {
844        unmount_all_devices(mountlist);
845        log_to_screen
846            (_("Unable to mount all partitions. Sorry, I cannot proceed."));
847        return (retval);
848    }
849    iamhere("Restoring everything");
850    retval += restore_everything(bkpinfo, NULL);
851    if (!run_boot_loader(FALSE)) {
852        mr_msg(1,
853                "Great! Boot loader was installed. No need for msg at end.");
854        boot_loader_installed = TRUE;
855    }
856    clean_blkid(bkpinfo);
857    protect_against_braindead_sysadmins();
858    retval += unmount_all_devices(mountlist);
859    mvaddstr_and_log_it(g_currentY,
860                        0,
861                        _("Using tune2fs to identify your ext2,3 partitions"));
862
863    mr_asprintf(&tmp, "label-partitions-as-necessary %s < /tmp/fstab",
864            g_mountlist_fname);
865    res = run_program_and_log_output(tmp, TRUE);
866    mr_free(tmp);
867
868    if (res) {
869        log_to_screen(_("label-partitions-as-necessary returned an error"));
870        mvaddstr_and_log_it(g_currentY++, 74, _("Failed."));
871    } else {
872        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
873    }
874    retval += res;
875
876    call_me_after_the_nuke(retval);
877    return (retval);
878}
879
880/**************************************************************************
881 *END_NUKE_MODE                                                           *
882 **************************************************************************/
883
884
885/**
886 * Restore the user's data (or a subset of it) to the live filesystem.
887 * This should not be called if we're booted from CD!
888 * @param bkpinfo The backup information structure. Most fields are used.
889 * @return 0 for success, or the number of errors encountered.
890 */
891int restore_to_live_filesystem(struct s_bkpinfo *bkpinfo)
892{
893    int retval = 0;
894
895    char *old_restpath = NULL;
896
897    struct mountlist_itself *mountlist = NULL;
898    struct raidlist_itself *raidlist = NULL;
899    struct s_node *filelist = NULL;
900
901    mr_msg(1, "restore_to_live_filesystem() - starting");
902    assert(bkpinfo != NULL);
903
904    mountlist = mr_malloc(sizeof(struct mountlist_itself));
905    raidlist = mr_malloc(sizeof(struct raidlist_itself));
906
907    strcpy(bkpinfo->restore_path, "/");
908    if (!g_restoring_live_from_cd) {
909        popup_and_OK
910            (_("Please insert tape/CD, then hit 'OK' to continue."));
911        sleep(1);
912    }
913    interactively_obtain_media_parameters_from_user(bkpinfo, FALSE);
914    if (!bkpinfo->media_device) {
915        mr_msg(2, "Warning - failed to find media dev");
916    } else {
917        mr_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
918    }
919
920
921    mr_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
922
923    open_evalcall_form(_("Thinking..."));
924
925    get_cfg_file_from_archive_or_bust(bkpinfo);
926    read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
927    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
928
929    close_evalcall_form();
930    retval = load_mountlist(mountlist, g_mountlist_fname);
931    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
932    filelist = process_filelist_and_biggielist(bkpinfo);
933    if (filelist) {
934        save_filelist(filelist, "/tmp/selected-files.txt");
935        mr_asprintf(&old_restpath,bkpinfo->restore_path);
936        if (popup_and_get_string(_("Restore path"),
937                                 _("Restore files to where? "),
938                                 bkpinfo->restore_path, MAX_STR_LEN)) {
939            iamhere("Restoring everything");
940            retval += restore_everything(bkpinfo, filelist);
941        }
942        free_filelist(filelist);
943        strcpy(bkpinfo->restore_path, old_restpath);
944        mr_free(old_restpath);
945    }
946    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
947        mr_msg(2,
948                "Tape : I don't need to unmount or eject the CD-ROM.");
949    } else {
950        run_program_and_log_output("umount " MNT_CDROM, FALSE);
951        if (!bkpinfo->please_dont_eject) {
952            eject_device(bkpinfo->media_device);
953        }
954    }
955    run_program_and_log_output("umount " MNT_CDROM, FALSE);
956    if ((!bkpinfo->please_dont_eject) && (bkpinfo->media_device)) {
957        eject_device(bkpinfo->media_device);
958    }
959    mr_free(mountlist);
960    mr_free(raidlist);
961    return (retval);
962}
963
964/**************************************************************************
965 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
966 **************************************************************************/
967
968/* @} - end of restoreGroup */
969
970
971/**
972 * @addtogroup LLrestoreGroup
973 * @{
974 */
975/**
976 * Restore biggiefile @p bigfileno from the currently mounted CD.
977 * @param bkpinfo The backup information structure. Fields used:
978 * - @c bkpinfo->backup_media_type
979 * - @c bkpinfo->restore_path
980 * @param bigfileno The biggiefile number (starting from 0) to restore.
981 * @param filelist The node structure containing the list of files to restore.
982 * If the biggiefile is not in this list, it will be skipped (return value will
983 * still indicate success).
984 * @return 0 for success (or skip), nonzero for failure.
985 */
986int
987restore_a_biggiefile_from_CD(struct s_bkpinfo *bkpinfo,
988                             long bigfileno,
989                             struct s_node *filelist,
990                             char *pathname_of_last_file_restored)
991{
992    FILE *fin = NULL;
993    FILE *fout = NULL;
994    FILE *fbzip2 = NULL;
995
996    char *checksum = NULL;
997    char *outfile_fname = NULL;
998    char *tmp = NULL;
999    char *bzip2_command = NULL;
1000    char *suffix = NULL;
1001    char *bigblk = NULL;
1002    int retval = 0;
1003    int finished = FALSE;
1004    long sliceno = 0L;
1005    long siz;
1006    char *ntfsprog_fifo = NULL;
1007    char *file_to_openout = NULL;
1008    struct s_filename_and_lstat_info biggiestruct;
1009    struct utimbuf the_utime_buf, *ubuf = NULL;
1010    bool use_ntfsprog_hack = FALSE;
1011    pid_t pid;
1012    int res = 0;
1013    int old_loglevel;
1014    struct s_node *node = NULL;
1015
1016    old_loglevel = g_loglevel;
1017    ubuf = &the_utime_buf;
1018    assert(bkpinfo != NULL);
1019
1020    pathname_of_last_file_restored[0] = '\0';
1021    bigblk = mr_malloc(TAPE_BLOCK_SIZE);
1022
1023    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1024        log_to_screen("Cannot even open bigfile's info file");
1025        return (1);
1026    }
1027
1028    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1029    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1030        sizeof(biggiestruct)) {
1031        mr_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1032                bigfileno + 1);
1033    }
1034    paranoid_fclose(fin);
1035
1036    mr_asprintf(&checksum, biggiestruct.checksum);
1037
1038    if (!checksum[0]) {
1039        mr_msg(3, "Warning - bigfile %ld does not have a checksum",
1040                bigfileno + 1);
1041    }
1042    mr_free(checksum);
1043
1044    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
1045    {
1046        mr_asprintf(&outfile_fname, biggiestruct.filename);
1047    } else {
1048        mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
1049                biggiestruct.filename);
1050    }
1051
1052    /* skip file if we have a selective restore subset & it doesn't match */
1053    if (filelist != NULL) {
1054        node = find_string_at_node(filelist, biggiestruct.filename);
1055        if (!node) {
1056            mr_msg(0, "Skipping %s (name isn't in filelist)",
1057                    biggiestruct.filename);
1058            return (0);
1059        } else if (!(node->selected)) {
1060            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
1061                    biggiestruct.filename);
1062            return (0);
1063        }
1064    }
1065    /* otherwise, continue */
1066
1067    mr_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1068    if (biggiestruct.use_ntfsprog) {
1069        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1070            mr_msg(1,
1071                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1072            mr_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1073            biggiestruct.use_ntfsprog = FALSE;
1074        }
1075    }
1076
1077    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
1078    {
1079        g_loglevel = 4;
1080        use_ntfsprog_hack = TRUE;
1081        mr_msg(2,
1082                "Calling ntfsclone in background because %s is an NTFS /dev entry",
1083                outfile_fname);
1084        mr_asprintf(&ntfsprog_fifo, "/tmp/%d.%d.000", (int) (random() % 32768),
1085                (int) (random() % 32768));
1086        mkfifo(ntfsprog_fifo, 0x770);
1087
1088        file_to_openout = ntfsprog_fifo;
1089        switch (pid = fork()) {
1090        case -1:
1091            fatal_error("Fork failure");
1092        case 0:
1093            mr_msg(3,
1094                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1095                    biggiestruct.filename, ntfsprog_fifo);
1096            res =
1097                feed_outfrom_ntfsprog(biggiestruct.filename,
1098                                      ntfsprog_fifo);
1099            exit(res);
1100            break;
1101        default:
1102            mr_msg(3,
1103                    "feed_into_ntfsprog() called in background --- pid=%ld",
1104                    (long int) (pid));
1105        }
1106    } else {
1107        use_ntfsprog_hack = FALSE;
1108        file_to_openout = outfile_fname;
1109        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1110        {
1111            make_hole_for_file(outfile_fname);
1112        }
1113    }
1114
1115    mr_msg(2, "Reassembling big file %ld (%s)", bigfileno + 1,
1116            outfile_fname);
1117
1118    /*
1119       last slice is zero-length and uncompressed; when we find it, we stop.
1120       We DON'T wait until there are no more slices; if we did that,
1121       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1122     */
1123
1124    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1125            MAX_STR_LEN - 1);
1126    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1127
1128    mr_msg(3, "file_to_openout = %s", file_to_openout);
1129    if (!(fout = fopen(file_to_openout, "w"))) {
1130        log_to_screen(_("Cannot openout file_to_openout - hard disk full?"));
1131        return (1);
1132    }
1133
1134    mr_free(ntfsprog_fifo);
1135    mr_msg(3, "Opened out to %s", outfile_fname);   // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1136
1137    for (sliceno = 1, finished = FALSE; !finished;) {
1138        if (!does_file_exist
1139            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1140            &&
1141            !does_file_exist(slice_fname
1142                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1143            &&
1144            !does_file_exist(slice_fname
1145                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1146            &&
1147            !does_file_exist(slice_fname
1148                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1149            mr_msg(3,
1150                    "Cannot find a data slice or terminator slice on CD %d",
1151                    g_current_media_number);
1152            g_current_media_number++;
1153            mr_msg(2, "Asking for %s #%d so that I may read slice #%ld\n",
1154                    media_descriptor_string(bkpinfo->backup_media_type),
1155                    g_current_media_number, sliceno);
1156            log_to_screen(_("Restoring from %s #%d"),
1157                    bkpinfo->backup_media_string,
1158                    g_current_media_number);
1159            insist_on_this_cd_number(bkpinfo, g_current_media_number);
1160            log_to_screen(_("Continuing to restore."));
1161        } else {
1162            mr_asprintf(&tmp,
1163                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1164            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1165                mr_msg(2,
1166                        "End of bigfile # %ld (slice %ld is the terminator)",
1167                        bigfileno + 1, sliceno);
1168                finished = TRUE;
1169                mr_free(tmp);
1170                continue;
1171            } else {
1172                mr_free(tmp);
1173                if (does_file_exist
1174                    (slice_fname
1175                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1176                    mr_asprintf(&bzip2_command, "lzop");
1177                    mr_asprintf(&suffix, "lzo");
1178                } else
1179                    if (does_file_exist
1180                        (slice_fname
1181                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1182                    mr_asprintf(&bzip2_command, "gzip");
1183                    mr_asprintf(&suffix, "gz");
1184                } else
1185                    if (does_file_exist
1186                        (slice_fname
1187                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1188                    mr_asprintf(&bzip2_command, "bzip2");
1189                    mr_asprintf(&suffix, "bz2");
1190                } else
1191                    if (does_file_exist
1192                        (slice_fname
1193                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1194                    mr_asprintf(&bzip2_command, "");
1195                    mr_asprintf(&suffix, "");
1196                } else {
1197                    log_to_screen(_("OK, that's pretty fsck0red..."));
1198                    return (1);
1199                }
1200            }
1201            if (bzip2_command[0] != '\0') {
1202                mr_strcat(bzip2_command,
1203                        " -dc %s 2>> %s",
1204                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1205                                    suffix), MONDO_LOGFILE);
1206            } else {
1207                mr_free(bzip2_command);
1208                mr_asprintf(&bzip2_command, "cat %s 2>> %s",
1209                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1210                                    suffix), MONDO_LOGFILE);
1211            }
1212            mr_asprintf(&tmp, "Working on %s #%d, file #%ld, slice #%ld",
1213                    bkpinfo->backup_media_string,
1214                    g_current_media_number, bigfileno + 1, sliceno);
1215            mr_msg(2, tmp);
1216            if (!g_text_mode) {
1217                newtDrawRootText(0, g_noof_rows - 2, tmp);
1218                newtRefresh();
1219                update_progress_form(tmp);
1220            }
1221            mr_free(tmp);
1222
1223            if (!(fbzip2 = popen(bzip2_command, "r"))) {
1224                mr_free(bzip2_command);
1225                mr_free(suffix);
1226                fatal_error("Can't run popen command");
1227            }
1228            mr_free(bzip2_command);
1229            mr_free(suffix);
1230
1231            while (!feof(fbzip2)) {
1232                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1233                if (siz > 0) {
1234                    siz = fwrite(bigblk, 1, siz, fout);
1235                }
1236            }
1237            paranoid_pclose(fbzip2);
1238
1239            sliceno++;
1240            g_current_progress++;
1241        }
1242    }
1243    paranoid_fclose(fout);
1244    g_loglevel = old_loglevel;
1245
1246    if (use_ntfsprog_hack) {
1247        mr_msg(3, "Waiting for ntfsclone to finish");
1248        mr_asprintf(&tmp,
1249                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1250        while (system(tmp) == 0) {
1251            sleep(1);
1252        }
1253        mr_free(tmp);
1254        log_it("OK, ntfsclone has really finished");
1255    }
1256
1257    if (strcmp(outfile_fname, "/dev/null")) {
1258        chown(outfile_fname, biggiestruct.properties.st_uid,
1259              biggiestruct.properties.st_gid);
1260        chmod(outfile_fname, biggiestruct.properties.st_mode);
1261        ubuf->actime = biggiestruct.properties.st_atime;
1262        ubuf->modtime = biggiestruct.properties.st_mtime;
1263        utime(outfile_fname, ubuf);
1264    }
1265    mr_free(outfile_fname);
1266    mr_free(bigblk);
1267
1268    return (retval);
1269}
1270
1271
1272/**************************************************************************
1273 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
1274 **************************************************************************/
1275
1276
1277/**
1278 * Restore a biggiefile from the currently opened stream.
1279 * @param bkpinfo The backup information structure. Fields used:
1280 * - @c bkpinfo->restore_path
1281 * - @c bkpinfo->zip_exe
1282 * @param orig_bf_fname The original filename of the biggiefile.
1283 * @param biggiefile_number The number of the biggiefile (starting from 0).
1284 * @param filelist The node structure containing the list of files to be restored.
1285 * If @p orig_bf_fname is not in the list, it will be ignored.
1286 * @return 0 for success (or skip), nonzero for failure.
1287 */
1288int restore_a_biggiefile_from_stream(struct s_bkpinfo *bkpinfo, char *orig_bf_fname, long biggiefile_number, char *orig_checksum,   //UNUSED
1289                                     long long biggiefile_size, //UNUSED
1290                                     struct s_node *filelist,
1291                                     int use_ntfsprog,
1292                                     char *pathname_of_last_file_restored)
1293{
1294    FILE *pout = NULL;
1295    FILE *fin = NULL;
1296
1297  /** mallocs ********/
1298    char *tmp = NULL;
1299    char *tmp1 = NULL;
1300    char *command = NULL;
1301    char *outfile_fname = NULL;
1302    char *ntfsprog_fifo = NULL;
1303    char *file_to_openout = NULL;
1304
1305    struct s_node *node = NULL;
1306
1307    int old_loglevel = 0;
1308    long current_slice_number = 0;
1309    int retval = 0;
1310    int res = 0;
1311    int ctrl_chr = '\0';
1312    long long slice_siz = 0L;
1313    bool dummy_restore = FALSE;
1314    bool use_ntfsprog_hack = FALSE;
1315    pid_t pid;
1316    struct s_filename_and_lstat_info biggiestruct;
1317    struct utimbuf the_utime_buf, *ubuf = NULL;
1318    ubuf = &the_utime_buf;
1319
1320    old_loglevel = g_loglevel;
1321    assert(bkpinfo != NULL);
1322    assert(orig_bf_fname != NULL);
1323    assert(orig_checksum != NULL);
1324
1325    pathname_of_last_file_restored[0] = '\0';
1326    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1327        use_ntfsprog = 1;
1328        mr_msg(1, "%s --- pih=YES", orig_bf_fname);
1329    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1330        use_ntfsprog = 0;
1331        mr_msg(1, "%s --- pih=NO", orig_bf_fname);
1332    } else {
1333        use_ntfsprog = 0;
1334        mr_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1335    }
1336
1337    strncpy(pathname_of_last_file_restored, orig_bf_fname,
1338            MAX_STR_LEN - 1);
1339    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1340
1341    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1342
1343    if (filelist != NULL) {
1344        node = find_string_at_node(filelist, orig_bf_fname);
1345        if (!node) {
1346            dummy_restore = TRUE;
1347            mr_msg(1,
1348                    "Skipping big file %ld (%s) - not in biggielist subset",
1349                    biggiefile_number + 1, orig_bf_fname);
1350            pathname_of_last_file_restored[0] = '\0';
1351        } else if (!(node->selected)) {
1352            dummy_restore = TRUE;
1353            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
1354                    orig_bf_fname);
1355            pathname_of_last_file_restored[0] = '\0';
1356        }
1357    }
1358
1359    if (use_ntfsprog) {
1360        if (strncmp(orig_bf_fname, "/dev/", 5)) {
1361            mr_msg(1, "I was in error when I set use_ntfsprog to TRUE.");
1362            mr_msg(1, "%s isn't even in /dev", orig_bf_fname);
1363            use_ntfsprog = FALSE;
1364        }
1365    }
1366
1367    if (use_ntfsprog) {
1368        g_loglevel = 4;
1369        mr_asprintf(&outfile_fname, orig_bf_fname);
1370        use_ntfsprog_hack = TRUE;
1371        mr_msg(2,
1372                "Calling ntfsclone in background because %s is a /dev entry",
1373                outfile_fname);
1374        mr_asprintf(&ntfsprog_fifo, "%s/%d.%d.000", 
1375                bkpinfo->tmpdir,
1376                (int) (random() % 32768),
1377                (int) (random() % 32768));
1378        mkfifo(ntfsprog_fifo, 0x770);
1379
1380        file_to_openout = ntfsprog_fifo;
1381        switch (pid = fork()) {
1382        case -1:
1383            fatal_error("Fork failure");
1384        case 0:
1385            mr_msg(3,
1386                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1387                    outfile_fname, ntfsprog_fifo);
1388            res = feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1389            exit(res);
1390            break;
1391        default:
1392            mr_msg(3,
1393                    "feed_into_ntfsprog() called in background --- pid=%ld",
1394                    (long int) (pid));
1395        }
1396    } else {
1397        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
1398        {
1399            mr_asprintf(&outfile_fname, orig_bf_fname);
1400        } else                  // biggiefile
1401        {
1402            mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
1403                    orig_bf_fname);
1404        }
1405        use_ntfsprog_hack = FALSE;
1406        file_to_openout = outfile_fname;
1407        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1408        {
1409            make_hole_for_file(outfile_fname);
1410        }
1411        mr_msg(2, "Reassembling big file %ld (%s)",
1412                biggiefile_number + 1, orig_bf_fname);
1413    }
1414
1415    if (dummy_restore) {
1416        mr_free(outfile_fname);
1417        mr_asprintf(&outfile_fname, "/dev/null");
1418    }
1419
1420    if (!bkpinfo->zip_exe[0]) {
1421        mr_asprintf(&command, "cat > \"%s\"", file_to_openout);
1422    } else {
1423        mr_asprintf(&command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1424                file_to_openout, MONDO_LOGFILE);
1425    }
1426    mr_msg(3, "Pipe command = '%s'", command);
1427    mr_free(outfile_fname);
1428    mr_free(ntfsprog_fifo);
1429
1430    /* restore biggiefile, one slice at a time */
1431    if (!(pout = popen(command, "w"))) {
1432        fatal_error("Cannot pipe out");
1433    }
1434    mr_free(command);
1435
1436    malloc_string(tmp1);
1437    for (res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1438         ctrl_chr != BLK_STOP_A_BIGGIE;
1439         res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr)) {
1440        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1441            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1442        }
1443        mr_asprintf(&tmp, "Working on file #%ld, slice #%ld    ",
1444                biggiefile_number + 1, current_slice_number);
1445        mr_msg(2, tmp);
1446        if (!g_text_mode) {
1447            newtDrawRootText(0, g_noof_rows - 2, tmp);
1448            newtRefresh();
1449        }
1450        mr_strip_spaces(tmp);
1451        update_progress_form(tmp);
1452        mr_free(tmp);
1453        if (current_slice_number == 0) {
1454            res =
1455                read_file_from_stream_to_file(bkpinfo,
1456                                              "/tmp/biggie-blah.txt",
1457                                              slice_siz);
1458            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1459                log_OS_error("blah blah");
1460            } else {
1461                if (fread
1462                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1463                     fin) < sizeof(biggiestruct)) {
1464                    mr_msg(2,
1465                            "Warning - unable to get biggiestruct of bigfile #%d",
1466                            biggiefile_number + 1);
1467                }
1468                paranoid_fclose(fin);
1469            }
1470        } else {
1471            res =
1472                read_file_from_stream_to_stream(bkpinfo, pout, slice_siz);
1473        }
1474        retval += res;
1475        res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1476        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1477            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1478        }
1479        current_slice_number++;
1480        g_current_progress++;
1481    }
1482    mr_free(tmp1);
1483    paranoid_pclose(pout);
1484
1485    mr_msg(1, "pathname_of_last_file_restored is now %s",
1486            pathname_of_last_file_restored);
1487
1488    if (use_ntfsprog_hack) {
1489        mr_msg(3, "Waiting for ntfsclone to finish");
1490        mr_asprintf(&tmp,
1491                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1492        while (system(tmp) == 0) {
1493            sleep(1);
1494        }   
1495        mr_free(tmp);
1496        mr_msg(3, "OK, ntfsclone has really finished");
1497    }
1498
1499    mr_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1500    mr_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1501    if (strcmp(outfile_fname, "/dev/null")) {
1502        chmod(outfile_fname, biggiestruct.properties.st_mode);
1503        chown(outfile_fname, biggiestruct.properties.st_uid,
1504              biggiestruct.properties.st_gid);
1505        ubuf->actime = biggiestruct.properties.st_atime;
1506        ubuf->modtime = biggiestruct.properties.st_mtime;
1507        utime(outfile_fname, ubuf);
1508    }
1509
1510    g_loglevel = old_loglevel;
1511    return (retval);
1512}
1513
1514/**************************************************************************
1515 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
1516 **************************************************************************/
1517
1518
1519/**
1520 * Restore @p tarball_fname from CD.
1521 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1522 * This will be used unmodified.
1523 * @param current_tarball_number The number (starting from 0) of the fileset
1524 * we're restoring now.
1525 * @param filelist The node structure containing the list of files to be
1526 * restored. If no file in the afioball is in this list, afio will still be
1527 * called, but nothing will be written.
1528 * @return 0 for success, nonzero for failure.
1529 */
1530int
1531restore_a_tarball_from_CD(char *tarball_fname,
1532                          long current_tarball_number,
1533                          struct s_node *filelist, struct s_bkpinfo *bkpinfo)
1534{
1535    int retval = 0;
1536    int res = 0;
1537    char *p = NULL;
1538
1539  /** malloc **/
1540    char *command = NULL;
1541    char *tmp = NULL;
1542    char *filelist_name = NULL;
1543    char *filelist_subset_fname = NULL;
1544    char *executable = NULL;
1545    char *temp_log = NULL;
1546    long matches = 0;
1547    bool use_star = FALSE;
1548    char *xattr_fname = NULL;
1549    char *acl_fname = NULL;
1550
1551    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1552
1553    mr_msg(5, "Entering");
1554    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1555    mr_asprintf(&command, "mkdir -p %s/tmp", MNT_RESTORING);
1556    run_program_and_log_output(command, 9);
1557    mr_free(command);
1558
1559    mr_asprintf(&filelist_name, MNT_CDROM "/archives/filelist.%ld",
1560            current_tarball_number);
1561    if (length_of_file(filelist_name) <= 2) {
1562        mr_msg(2, "There are _zero_ files in filelist '%s'",
1563                filelist_name);
1564        mr_msg(2,
1565                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1566        mr_msg(2,
1567                "but it's non-critical. It's cosmetic. Don't worry about it.");
1568        retval = 0;
1569        mr_msg(5, "Leaving");
1570        mr_free(filelist_name);
1571        return (retval);
1572    }
1573    if (count_lines_in_file(filelist_name) <= 0
1574        || length_of_file(tarball_fname) <= 0) {
1575        mr_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1576                length_of_file(tarball_fname));
1577        log_to_screen(_("Unable to restore fileset #%ld (CD I/O error)"),
1578                current_tarball_number);
1579        retval = 1;
1580        mr_msg(5, "Leaving");
1581        mr_free(filelist_name);
1582        return (retval);
1583    }
1584
1585    if (filelist) {
1586        mr_asprintf(&filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1587                current_tarball_number);
1588        if ((matches =
1589             save_filelist_entries_in_common(filelist_name, filelist,
1590                                             filelist_subset_fname,
1591                                             use_star))
1592            <= 0) {
1593            mr_msg(1, "Skipping fileset %ld", current_tarball_number);
1594        } else {
1595            mr_msg(3, "Saved fileset %ld's subset to %s",
1596                    current_tarball_number, filelist_subset_fname);
1597        }
1598        log_to_screen("Tarball #%ld --- %ld matches",
1599                current_tarball_number, matches);
1600    }
1601    mr_free(filelist_name);
1602
1603    if (filelist == NULL || matches > 0) {
1604        if (g_getfattr) {
1605            mr_asprintf(&xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1606                MNT_CDROM "/archives", current_tarball_number);
1607        }
1608        if (g_getfacl) {
1609            mr_asprintf(&acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1610                current_tarball_number);
1611        }
1612        if (strstr(tarball_fname, ".bz2")) {
1613            mr_asprintf(&executable, "-P bzip2 -Z");
1614        } else if (strstr(tarball_fname, ".gz")) {
1615            mr_asprintf(&executable, "-P gzip -Z");
1616        } else if (strstr(tarball_fname, ".lzo")) {
1617            mr_asprintf(&executable, "-P lzop -Z");
1618        }
1619
1620        if (executable == NULL) {
1621            mr_asprintf(&tmp, "which %s > /dev/null 2> /dev/null", executable);
1622            if (run_program_and_log_output(tmp, FALSE)) {
1623                log_to_screen
1624                    (_("(compare_a_tarball) Compression program not found - oh no!"));
1625                mr_free(tmp);
1626                mr_free(executable);
1627                mr_free(acl_fname);
1628                mr_free(xattr_fname);
1629                mr_free(filelist_subset_fname);
1630                paranoid_MR_finish(1);
1631            }
1632            mr_free(tmp);
1633        }
1634#ifdef __FreeBSD__
1635#define BUFSIZE 512
1636#else
1637#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1638#endif
1639
1640        if (use_star) {
1641            mr_asprintf(&command,
1642                    "star -x -force-remove -U " STAR_ACL_SZ
1643                    " errctl= file=%s", tarball_fname);
1644            if (strstr(tarball_fname, ".bz2")) {
1645                mr_strcat(command, " -bz");
1646            }
1647        } else {
1648            if (filelist_subset_fname != NULL) {
1649                mr_asprintf(&command,
1650                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1651                        TAPE_BLOCK_SIZE,
1652                        BUFSIZE, executable, filelist_subset_fname,
1653                        tarball_fname);
1654            } else {
1655                mr_asprintf(&command,
1656                        "afio -i -b %ld -c %ld -M 8m %s %s",
1657                        TAPE_BLOCK_SIZE,
1658                        BUFSIZE, executable, tarball_fname);
1659            }
1660        }
1661        mr_free(executable);
1662
1663#undef BUFSIZE
1664        mr_asprintf(&temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1665            (int) (random() % 32768));
1666
1667        mr_strcat(command, " 2>> %s >> %s", temp_log, temp_log);
1668        mr_msg(1, "command = '%s'", command);
1669        unlink(temp_log);
1670        res = system(command);
1671        if (res) {
1672            p = strstr(command, "-acl ");
1673            if (p) {
1674                p[0] = p[1] = p[2] = p[3] = ' ';
1675                mr_msg(1, "new command = '%s'", command);
1676                res = system(command);
1677            }
1678        }
1679        mr_free(command);
1680
1681        if (res && length_of_file(temp_log) < 5) {
1682            res = 0;
1683        }
1684
1685        if (g_getfattr) {
1686            mr_msg(1, "Setting fattr list %s", xattr_fname);
1687            if (length_of_file(xattr_fname) > 0) {
1688                res = set_fattr_list(filelist_subset_fname, xattr_fname);
1689                if (res) {
1690                    log_to_screen
1691                        ("Errors occurred while setting extended attributes");
1692                } else {
1693                    mr_msg(1, "I set xattr OK");
1694                }
1695                retval += res;
1696            }
1697        }
1698        if (g_getfacl) {
1699            mr_msg(1, "Setting acl list %s", acl_fname);
1700            if (length_of_file(acl_fname) > 0) {
1701                res = set_acl_list(filelist_subset_fname, acl_fname);
1702                if (res) {
1703                    log_to_screen
1704                        ("Errors occurred while setting access control lists");
1705                } else {
1706                    mr_msg(1, "I set ACL OK");
1707                }
1708                retval += res;
1709            }
1710        }
1711        if (retval) {
1712            mr_asprintf(&command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1713            system(command);
1714            mr_free(command);
1715            mr_msg(2, "Errors occurred while processing fileset #%d",
1716                    current_tarball_number);
1717        } else {
1718            mr_msg(2, "Fileset #%d processed OK", current_tarball_number);
1719        }
1720        unlink(xattr_fname);
1721        mr_free(xattr_fname);
1722        unlink(acl_fname);
1723        mr_free(acl_fname);
1724        unlink(temp_log);
1725        mr_free(temp_log);
1726    }
1727    if (does_file_exist("/PAUSE")) {
1728        popup_and_OK
1729            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
1730    }
1731    unlink(filelist_subset_fname);
1732    mr_free(filelist_subset_fname);
1733    mr_msg(5, "Leaving");
1734    return (retval);
1735}
1736
1737/**************************************************************************
1738 *END_RESTORE_A_TARBALL_FROM_CD                                           *
1739 **************************************************************************/
1740
1741
1742/**
1743 * Restore a tarball from the currently opened stream.
1744 * @param bkpinfo The backup information structure. Fields used:
1745 * - @c bkpinfo->backup_media_type
1746 * - @c bkpinfo->media_device
1747 * - @c bkpinfo->zip_exe
1748 * @param tarball_fname The filename of the afioball to restore.
1749 * @param current_tarball_number The number (starting from 0) of the fileset
1750 * we're restoring now.
1751 * @param filelist The node structure containing the list of files to be
1752 * restored. If no file in the afioball is in this list, afio will still be
1753 * called, but nothing will be written.
1754 * @param size The size (in @b bytes) of the afioball.
1755 * @return 0 for success, nonzero for failure.
1756 */
1757int
1758restore_a_tarball_from_stream(struct s_bkpinfo *bkpinfo,
1759                              char *tarball_fname,
1760                              long current_tarball_number,
1761                              struct s_node *filelist,
1762                              long long size, char *xattr_fname,
1763                              char *acl_fname)
1764{
1765    int retval = 0;
1766    int res = 0;
1767
1768  /** malloc add ***/
1769    char *command = NULL;
1770    char *afio_fname = NULL;
1771    char *filelist_fname = NULL;
1772    char *filelist_subset_fname = NULL;
1773    char *executable = NULL;
1774    long matches = 0;
1775    bool restore_this_fileset = FALSE;
1776    bool use_star = FALSE;
1777
1778    assert(bkpinfo != NULL);
1779    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1780    /* to do it with a file... */
1781    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1782    mr_msg(2, "Restoring from fileset #%ld (%ld KB) on %s #%d",
1783            current_tarball_number, (long) size >> 10,
1784            bkpinfo->backup_media_string,
1785            g_current_media_number);
1786    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1787
1788  /****************************************************************************
1789   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
1790   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
1791   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
1792   ****************************************************************************/
1793    mr_asprintf(&afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1794            current_tarball_number);
1795    mr_asprintf(&filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1796            current_tarball_number);
1797    mr_asprintf(&filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1798            bkpinfo->tmpdir, current_tarball_number);
1799    res = read_file_from_stream_to_file(bkpinfo, afio_fname, size);
1800    if (strstr(tarball_fname, ".star")) {
1801        bkpinfo->use_star = TRUE;
1802    }
1803    if (res) {
1804        mr_msg(1, "Warning - error reading afioball from tape");
1805    }
1806    if (bkpinfo->compression_level != 0) {
1807        if (bkpinfo->use_star) {
1808            mr_asprintf(&executable, " -bz");
1809        } else {
1810            mr_asprintf(&executable, "-P %s -Z", bkpinfo->zip_exe);
1811        }
1812    }
1813
1814    if (!filelist)              // if unconditional restore then restore entire fileset
1815    {
1816        restore_this_fileset = TRUE;
1817    } else                      // If restoring selectively then get TOC from tarball
1818    {
1819        if (strstr(tarball_fname, ".star.")) {
1820            use_star = TRUE;
1821            mr_asprintf(&command, "star -t file=%s %s", afio_fname, executable);
1822        } else {
1823            use_star = FALSE;
1824            mr_asprintf(&command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1825                    executable, afio_fname);
1826        }
1827        mr_strcat(command, " > %s 2>> %s", filelist_fname, MONDO_LOGFILE);
1828        mr_msg(1, "command = %s", command);
1829        if (system(command)) {
1830            mr_msg(4, "Warning - error occurred while retrieving TOC");
1831        }
1832        mr_free(command);
1833
1834        if ((matches =
1835             save_filelist_entries_in_common(filelist_fname, filelist,
1836                                             filelist_subset_fname,
1837                                             use_star))
1838            <= 0 || length_of_file(filelist_subset_fname) < 2) {
1839            if (length_of_file(filelist_subset_fname) < 2) {
1840                mr_msg(1, "No matches found in fileset %ld",
1841                        current_tarball_number);
1842            }
1843            mr_msg(2, "Skipping fileset %ld", current_tarball_number);
1844            restore_this_fileset = FALSE;
1845        } else {
1846            mr_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1847                    matches, current_tarball_number,
1848                    filelist_subset_fname);
1849            restore_this_fileset = TRUE;
1850        }
1851    }
1852    unlink(filelist_fname);
1853    mr_free(filelist_fname);
1854
1855// Concoct the call to star/afio to restore files
1856    if (strstr(tarball_fname, ".star.")) {
1857        // star
1858        if (filelist) {
1859            mr_asprintf(&command, "star -x file=%s %s list=%s 2>> %s", afio_fname, executable, filelist_subset_fname, MONDO_LOGFILE);
1860        } else {
1861            mr_asprintf(&command, "star -x file=%s %s 2>> %s", afio_fname, executable, MONDO_LOGFILE);
1862        }
1863    } else {
1864        // afio
1865        if (filelist) {
1866            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);
1867        } else {
1868            mr_asprintf(&command, "afio -i -M 8m -b %ld %s %s 2>> %s", TAPE_BLOCK_SIZE, executable, afio_fname, MONDO_LOGFILE);
1869        }
1870    }
1871    mr_free(executable);
1872
1873    // Call if IF there are files to restore (selectively/unconditionally)
1874    if (restore_this_fileset) {
1875        mr_msg(1, "Calling command='%s'", command);
1876        paranoid_system(command);
1877
1878        if (g_getfattr) {
1879            iamhere("Restoring xattr stuff");
1880            res = set_fattr_list(filelist_subset_fname, xattr_fname);
1881            if (res) {
1882                mr_msg(1, "Errors occurred while setting xattr");
1883            } else {
1884                mr_msg(1, "I set xattr OK");
1885            }
1886            retval += res;
1887        }
1888
1889        if (g_getfacl) {
1890            iamhere("Restoring acl stuff");
1891            res = set_acl_list(filelist_subset_fname, acl_fname);
1892            if (res) {
1893                mr_msg(1, "Errors occurred while setting ACL");
1894            } else {
1895                mr_msg(1, "I set ACL OK");
1896            }
1897            retval += res;
1898        }
1899
1900    } else {
1901        mr_msg(1, "NOT CALLING '%s'", command);
1902    }
1903    mr_free(command);
1904
1905    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1906        log_to_screen(_("Paused after set %ld"), current_tarball_number);
1907        popup_and_OK(_("Pausing. Press ENTER to continue."));
1908    }
1909
1910    unlink(filelist_subset_fname);
1911    unlink(afio_fname);
1912
1913    mr_free(filelist_subset_fname);
1914    mr_free(afio_fname);
1915    return (retval);
1916}
1917
1918/**************************************************************************
1919 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
1920 **************************************************************************/
1921
1922
1923/**
1924 * Restore all biggiefiles from all media in this CD backup.
1925 * The CD with the last afioball should be currently mounted.
1926 * @param bkpinfo The backup information structure. @c backup_media_type is the
1927 * only field used in this function.
1928 * @param filelist The node structure containing the list of files to be
1929 * restored. If a prospective biggiefile is not in this list, it will be ignored.
1930 * @return 0 for success, nonzero for failure.
1931 */
1932int
1933restore_all_biggiefiles_from_CD(struct s_bkpinfo *bkpinfo,
1934                                struct s_node *filelist)
1935{
1936    int retval = 0;
1937    int res = 0;
1938    long noof_biggiefiles = 0L, bigfileno = 0L, total_slices = 0L;
1939    char *tmp = NULL;
1940    char *tmp1 = NULL;
1941    bool just_changed_cds = FALSE, finished = FALSE;
1942    char *xattr_fname = NULL;
1943    char *acl_fname = NULL;
1944    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
1945    char *pathname_of_last_biggie_restored = NULL;
1946    FILE *fbw = NULL;
1947
1948    malloc_string(tmp1);
1949    malloc_string(pathname_of_last_biggie_restored);
1950    assert(bkpinfo != NULL);
1951
1952    mr_asprintf(&biggies_whose_EXATs_we_should_set,
1953            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
1954    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
1955        mr_msg(1, "Warning - cannot openout %s",
1956                biggies_whose_EXATs_we_should_set);
1957    }
1958
1959    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp1);
1960    total_slices = atol(tmp1);
1961    mr_free(tmp1);
1962
1963    mr_asprintf(&tmp, _("Reassembling large files      "));
1964    mvaddstr_and_log_it(g_currentY, 0, tmp);
1965    mr_free(tmp);
1966
1967    if (length_of_file(BIGGIELIST) < 6) {
1968        mr_msg(1, "OK, no biggielist; not restoring biggiefiles");
1969        return (0);
1970    }
1971    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
1972    if (noof_biggiefiles <= 0) {
1973        mr_msg(2,
1974                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
1975        return (0);
1976    }
1977    mr_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
1978
1979    open_progress_form(_("Reassembling large files"),
1980                       _("I am now reassembling all the large files."),
1981                       _("Please wait. This may take some time."),
1982                       "", total_slices);
1983    for (bigfileno = 0, finished = FALSE; !finished;) {
1984        mr_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
1985        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
1986            mr_msg(3,
1987                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
1988            mr_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
1989                    bigfileno + 1,
1990                    bkpinfo->backup_media_string,
1991                    g_current_media_number);
1992            mr_msg(3, "Slicename would have been %s",
1993                    slice_fname(bigfileno + 1, 0, ARCHIVES_PATH, ""));
1994            // I'm not positive 'just_changed_cds' is even necessary...
1995            if (just_changed_cds) {
1996                just_changed_cds = FALSE;
1997                mr_msg(3,
1998                        "I'll continue to scan this CD for bigfiles to be restored.");
1999            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2000                insist_on_this_cd_number(bkpinfo,
2001                                         ++g_current_media_number);
2002                log_to_screen(_("Restoring from %s #%d"),
2003                        bkpinfo->backup_media_string,
2004                        g_current_media_number);
2005                just_changed_cds = TRUE;
2006            } else {
2007                mr_msg(2, "There was no bigfile #%ld. That's OK.",
2008                        bigfileno + 1);
2009                mr_msg(2, "I'm going to stop restoring bigfiles now.");
2010                finished = TRUE;
2011            }
2012        } else {
2013            just_changed_cds = FALSE;
2014            mr_asprintf(&tmp, _("Restoring big file %ld"), bigfileno + 1);
2015            update_progress_form(tmp);
2016            mr_free(tmp);
2017
2018            res =
2019                restore_a_biggiefile_from_CD(bkpinfo, bigfileno, filelist,
2020                                             pathname_of_last_biggie_restored);
2021            iamhere(pathname_of_last_biggie_restored);
2022            if (fbw && pathname_of_last_biggie_restored[0]) {
2023                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2024            }
2025            retval += res;
2026            bigfileno++;
2027        }
2028    }
2029
2030    if (fbw) {
2031        fclose(fbw);
2032        if (g_getfattr) {
2033            mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2034            if (length_of_file(xattr_fname) > 0) {
2035                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2036            }
2037        }
2038        if (g_getfacl) {
2039            mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2040            if (length_of_file(acl_fname) > 0) {
2041                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2042            }
2043        }
2044        mr_free(acl_fname);
2045        mr_free(xattr_fname);
2046    }
2047    mr_free(biggies_whose_EXATs_we_should_set);
2048
2049    if (does_file_exist("/PAUSE")) {
2050        popup_and_OK
2051            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2052    }
2053    close_progress_form();
2054    if (retval) {
2055        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2056    } else {
2057        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2058    }
2059    mr_free(pathname_of_last_biggie_restored);
2060    return (retval);
2061}
2062
2063/**************************************************************************
2064 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2065 **************************************************************************/
2066
2067
2068/**
2069 * Restore all afioballs from all CDs in the backup.
2070 * The first CD should be inserted (if not, it will be asked for).
2071 * @param bkpinfo The backup information structure. @c backup_media_type is the
2072 * only field used in @e this function.
2073 * @param filelist The node structure containing the list of files to be
2074 * restored. If no file in some particular afioball is in this list, afio will
2075 * still be called for that fileset, but nothing will be written.
2076 * @return 0 for success, or the number of filesets that failed.
2077 */
2078int
2079restore_all_tarballs_from_CD(struct s_bkpinfo *bkpinfo,
2080                             struct s_node *filelist)
2081{
2082    int retval = 0;
2083    int res = 0;
2084    int attempts = 0;
2085    long current_tarball_number = 0;
2086    long max_val = 0L;
2087  /**malloc ***/
2088    char *tmp = NULL;
2089    char *tmp1 = NULL;
2090    char *tarball_fname = NULL;
2091    char *progress_str = NULL;
2092    char *comment = NULL;
2093
2094    malloc_string(tmp1);
2095    malloc_string(tarball_fname);
2096    malloc_string(progress_str);
2097    malloc_string(comment);
2098
2099    assert(bkpinfo != NULL);
2100
2101    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2102    mr_msg(2,
2103            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2104    if (g_current_media_number != 1) {
2105        mr_msg(3, "OK, that's jacked up.");
2106        g_current_media_number = 1;
2107    }
2108    insist_on_this_cd_number(bkpinfo, g_current_media_number);
2109    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp1);
2110    max_val = atol(tmp1) + 1;
2111    mr_free(tmp1);
2112
2113    mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2114            bkpinfo->backup_media_string,
2115            g_current_media_number);
2116    log_to_screen(progress_str);
2117    open_progress_form(_("Restoring from archives"),
2118                       _("Restoring data from the archives."),
2119                       _("Please wait. This may take some time."),
2120                       progress_str, max_val);
2121    for (;;) {
2122        insist_on_this_cd_number(bkpinfo, g_current_media_number);
2123        update_progress_form(progress_str);
2124        mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2125                current_tarball_number);
2126        if (!does_file_exist(tarball_fname)) {
2127            mr_free(tarball_fname);
2128            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2129                    current_tarball_number);
2130        }
2131        if (!does_file_exist(tarball_fname)) {
2132            mr_free(tarball_fname);
2133            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2134                current_tarball_number);
2135        }
2136        if (!does_file_exist(tarball_fname)) {
2137            mr_free(tarball_fname);
2138            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2139                    current_tarball_number);
2140        }
2141        if (!does_file_exist(tarball_fname)) {
2142            mr_free(tarball_fname);
2143            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2144                    current_tarball_number);
2145        }
2146        if (!does_file_exist(tarball_fname)) {
2147            mr_free(tarball_fname);
2148            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.",
2149                    current_tarball_number);
2150        }
2151        if (!does_file_exist(tarball_fname)) {
2152            mr_free(tarball_fname);
2153            if (current_tarball_number == 0) {
2154                log_to_screen
2155                    (_("No tarballs. Strange. Maybe you only backed up freakin' big files?"));
2156                mr_free(progress_str);
2157                return (0);
2158            }
2159            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2160                || system("find " MNT_CDROM
2161                          "/archives/slice* > /dev/null 2> /dev/null") ==
2162                0) {
2163                mr_free(tarball_fname);
2164                mr_free(progress_str);
2165                break;
2166            }
2167            g_current_media_number++;
2168            mr_free(progress_str);
2169
2170            mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2171                    bkpinfo->backup_media_string,
2172                    g_current_media_number);
2173            log_to_screen(progress_str);
2174        } else {
2175            mr_free(progress_str);
2176            mr_asprintf(&progress_str,
2177                    _("Restoring from fileset #%ld on %s #%d"),
2178                    current_tarball_number,
2179                    bkpinfo->backup_media_string,
2180                    g_current_media_number);
2181            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2182                 attempts++) {
2183                res =
2184                    restore_a_tarball_from_CD(tarball_fname,
2185                                              current_tarball_number,
2186                                              filelist, bkpinfo);
2187            }
2188            mr_asprintf(&tmp, _("%s #%d, fileset #%ld - restore "),
2189                    media_descriptor_string(bkpinfo->backup_media_type),
2190                    g_current_media_number, current_tarball_number);
2191            if (res) {
2192                mr_strcat(tmp, _("reported errors"));
2193            } else {
2194                mr_strcat(tmp, _("succeeded"));
2195            }
2196            if (attempts > 1) {
2197                mr_strcat(tmp, _(" (%d attempts) - review logs"), attempts);
2198            }
2199            if (attempts > 1) {
2200                log_to_screen(tmp);
2201            }
2202            mr_free(tmp);
2203
2204            retval += res;
2205            current_tarball_number++;
2206            g_current_progress++;
2207        }
2208        mr_free(tarball_fname);
2209    }
2210    mr_free(progress_str);
2211    close_progress_form();
2212
2213    if (retval) {
2214        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2215    } else {
2216        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2217    }
2218    return (retval);
2219}
2220
2221/**************************************************************************
2222 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2223 **************************************************************************/
2224
2225
2226/**
2227 * Restore all biggiefiles from the currently opened stream.
2228 * @param bkpinfo The backup information structure. Passed to other functions.
2229 * @param filelist The node structure containing the list of files to be
2230 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2231 * @return 0 for success, or the number of biggiefiles that failed.
2232 */
2233int
2234restore_all_biggiefiles_from_stream(struct s_bkpinfo *bkpinfo,
2235                                    struct s_node *filelist)
2236{
2237    long noof_biggiefiles = 0L;
2238    long current_bigfile_number = 0L;
2239    long total_slices = 0L;
2240
2241    int retval = 0;
2242    int res = 0;
2243    int ctrl_chr = 0;
2244
2245  /** malloc add ****/
2246    char *tmp = NULL;
2247    char *biggie_fname = NULL;
2248    char *biggie_cksum = NULL;
2249    char *xattr_fname = NULL;
2250    char *acl_fname = NULL;
2251    char *pathname_of_last_biggie_restored = NULL;
2252    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
2253    long long biggie_size = (long long)0;
2254    FILE *fbw;
2255
2256    assert(bkpinfo != NULL);
2257
2258    malloc_string(tmp);
2259    malloc_string(biggie_fname);
2260    malloc_string(biggie_cksum);
2261    malloc_string(pathname_of_last_biggie_restored);
2262    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2263    total_slices = atol(tmp);
2264    mr_free(tmp);
2265
2266    mr_asprintf(&tmp, "Reassembling large files      ");
2267    if (g_getfattr) {
2268        mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2269    }
2270    if (g_getfacl) {
2271        mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2272    }
2273    mvaddstr_and_log_it(g_currentY, 0, tmp);
2274    mr_free(tmp);
2275
2276    mr_asprintf(&biggies_whose_EXATs_we_should_set,
2277            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2278    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2279        mr_msg(1, "Warning - cannot openout %s",
2280                biggies_whose_EXATs_we_should_set);
2281    }
2282    // get xattr and acl files if they're there
2283    res =
2284        read_header_block_from_stream(&biggie_size, biggie_fname,
2285                                      &ctrl_chr);
2286    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2287        res =
2288            read_EXAT_files_from_tape(bkpinfo, &biggie_size, biggie_fname,
2289                                      &ctrl_chr, xattr_fname, acl_fname);
2290    }
2291
2292    noof_biggiefiles = atol(biggie_fname);
2293    mr_msg(2, "OK, there are %ld biggiefiles in the archives",
2294            noof_biggiefiles);
2295    open_progress_form(_("Reassembling large files"),
2296                       _("I am now reassembling all the large files."),
2297                       _("Please wait. This may take some time."),
2298                       "", total_slices);
2299
2300    for (res =
2301         read_header_block_from_stream(&biggie_size, biggie_fname,
2302                                       &ctrl_chr);
2303         ctrl_chr != BLK_STOP_BIGGIEFILES;
2304         res =
2305         read_header_block_from_stream(&biggie_size, biggie_fname,
2306                                       &ctrl_chr)) {
2307        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2308            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2309            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2310        }
2311        /* BERLIOS: useless
2312        p = strrchr(biggie_fname, '/');
2313        if (!p) {
2314            p = biggie_fname;
2315        } else {
2316            p++;
2317        }
2318        */
2319        mr_asprintf(&tmp, _("Restoring big file %ld (%lld K)"),
2320                current_bigfile_number + 1, biggie_size / 1024);
2321        update_progress_form(tmp);
2322        mr_free(tmp);
2323
2324        res = restore_a_biggiefile_from_stream(bkpinfo, biggie_fname,
2325                                               current_bigfile_number,
2326                                               biggie_cksum,
2327                                               biggie_size,
2328                                               filelist, ctrl_chr,
2329                                               pathname_of_last_biggie_restored);
2330        mr_msg(1, "I believe I have restored %s",
2331                pathname_of_last_biggie_restored);
2332        if (fbw && pathname_of_last_biggie_restored[0]) {
2333            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2334        }
2335        mr_free(pathname_of_last_biggie_restored);
2336
2337        retval += res;
2338        current_bigfile_number++;
2339
2340    }
2341    if (current_bigfile_number != noof_biggiefiles
2342        && noof_biggiefiles != 0) {
2343        mr_msg(1, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2344                current_bigfile_number, noof_biggiefiles);
2345    } else {
2346        mr_msg(1, "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2347                noof_biggiefiles, current_bigfile_number);
2348    }
2349
2350    if (fbw) {
2351        fclose(fbw);
2352        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2353            iamhere("Setting biggie-EXATs");
2354            if (g_getfattr) {
2355                if (length_of_file(xattr_fname) > 0) {
2356                    mr_msg(1, "set_fattr_List(%s,%s)",
2357                        biggies_whose_EXATs_we_should_set, xattr_fname);
2358                    set_fattr_list(biggies_whose_EXATs_we_should_set,
2359                               xattr_fname);
2360                }
2361            }
2362            if (g_getfacl) {
2363                if (length_of_file(acl_fname) > 0) {
2364                    mr_msg(1, "set_acl_list(%s,%s)",
2365                            biggies_whose_EXATs_we_should_set, acl_fname);
2366                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2367                }
2368            }
2369        } else {
2370            iamhere
2371                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2372        }
2373    }
2374    mr_free(xattr_fname);
2375    mr_free(acl_fname);
2376    mr_free(biggies_whose_EXATs_we_should_set);
2377
2378    if (does_file_exist("/PAUSE")) {
2379        popup_and_OK
2380            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2381    }
2382
2383    close_progress_form();
2384    if (retval) {
2385        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2386    } else {
2387        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2388    }
2389    mr_free(biggie_fname);
2390    mr_free(biggie_cksum);
2391    return (retval);
2392}
2393
2394/**************************************************************************
2395 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2396 **************************************************************************/
2397
2398
2399/**
2400 * Restore all afioballs from the currently opened tape stream.
2401 * @param bkpinfo The backup information structure. Fields used:
2402 * - @c bkpinfo->backup_media_type
2403 * - @c bkpinfo->restore_path
2404 * @param filelist The node structure containing the list of files to be
2405 * restored. If no file in an afioball is in this list, afio will still be
2406 * called for that fileset, but nothing will be written.
2407 * @return 0 for success, or the number of filesets that failed.
2408 */
2409int
2410restore_all_tarballs_from_stream(struct s_bkpinfo *bkpinfo,
2411                                 struct s_node *filelist)
2412{
2413    int retval = 0;
2414    int res = 0;
2415    long current_afioball_number = 0;
2416    int ctrl_chr = 0;
2417    long max_val = 0L /*, total_noof_files */ ;
2418
2419  /** malloc **/
2420    char *tmp = NULL;
2421    char *progress_str = NULL;
2422    char *tmp_fname = NULL;
2423    char *xattr_fname = NULL;
2424    char *acl_fname = NULL;
2425
2426    long long tmp_size = 0L;
2427
2428    malloc_string(tmp_fname);
2429    malloc_string(tmp);
2430    assert(bkpinfo != NULL);
2431    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2432    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2433    max_val = atol(tmp) + 1;
2434    mr_free(tmp);
2435
2436    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2437
2438    run_program_and_log_output("pwd", 5);
2439
2440    mr_asprintf(&progress_str, _("Restoring from media #%d"),
2441            g_current_media_number);
2442    log_to_screen(progress_str);
2443    open_progress_form(_("Restoring from archives"),
2444                       _("Restoring data from the archives."),
2445                       _("Please wait. This may take some time."),
2446                       progress_str, max_val);
2447
2448    mr_msg(3, "hey");
2449
2450    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2451    if (res) {
2452        mr_msg(2, "Warning - error reading afioball from tape");
2453    }
2454    retval += res;
2455    if (ctrl_chr != BLK_START_AFIOBALLS) {
2456        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2457    }
2458    mr_msg(2, "ho");
2459    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2460    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2461        update_progress_form(progress_str);
2462        if (g_getfattr) {
2463            mr_asprintf(&xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2464                current_afioball_number);
2465            unlink(xattr_fname);
2466        }
2467        if (g_getfacl) {
2468            mr_asprintf(&acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2469                current_afioball_number);
2470            unlink(acl_fname);
2471        }
2472        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2473            iamhere("Reading EXAT files from tape");
2474            res =
2475                read_EXAT_files_from_tape(bkpinfo, &tmp_size, tmp_fname,
2476                                          &ctrl_chr, xattr_fname,
2477                                          acl_fname);
2478        }
2479        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2480            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2481        }
2482        /* BERLIOS: useless ?
2483        mr_asprintf(&tmp,
2484                _("Restoring from fileset #%ld (name=%s, size=%ld K)"),
2485                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2486                */
2487        res =
2488            restore_a_tarball_from_stream(bkpinfo, tmp_fname,
2489                                          current_afioball_number,
2490                                          filelist, tmp_size, xattr_fname,
2491                                          acl_fname);
2492        retval += res;
2493        if (res) {
2494            log_to_screen("Fileset %ld - errors occurred",
2495                    current_afioball_number);
2496        }
2497        res =
2498            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2499        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2500            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2501        }
2502
2503        current_afioball_number++;
2504        g_current_progress++;
2505
2506        mr_free(progress_str);
2507        mr_asprintf(&progress_str, _("Restoring from fileset #%ld on %s #%d"),
2508                current_afioball_number,
2509                bkpinfo->backup_media_string,
2510                g_current_media_number);
2511        res =
2512            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2513        if (g_getfattr) {
2514            unlink(xattr_fname);
2515        }
2516        if (g_getfacl) {
2517            unlink(acl_fname);
2518        }
2519        mr_free(xattr_fname);
2520        mr_free(acl_fname);
2521    }                           // next
2522    mr_free(progress_str);
2523    mr_free(tmp_fname);
2524
2525    mr_msg(1, "All done with afioballs");
2526    close_progress_form();
2527    if (retval) {
2528        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2529    } else {
2530        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2531    }
2532    return (retval);
2533}
2534
2535/**************************************************************************
2536 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2537 **************************************************************************/
2538
2539/* @} - end of LLrestoreGroup */
2540
2541
2542/**
2543 * Restore all files in @p filelist.
2544 * @param bkpinfo The backup information structure. Most fields are used.
2545 * @param filelist The node structure containing the list of files to be
2546 * restored.
2547 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2548 * @ingroup restoreGroup
2549 */
2550int restore_everything(struct s_bkpinfo *bkpinfo, struct s_node *filelist)
2551{
2552    int resA;
2553    int resB;
2554
2555  /** mallco ***/
2556    char *cwd = NULL;
2557    char *newpath = NULL;
2558    char *tmp = NULL;
2559    assert(bkpinfo != NULL);
2560
2561    malloc_string(cwd);
2562    malloc_string(newpath);
2563    mr_msg(2, "restore_everything() --- starting");
2564    g_current_media_number = 1;
2565    /* BERLIOS: should test return value, or better change the function */
2566    getcwd(cwd, MAX_STR_LEN - 1);
2567    mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->restore_path);
2568    run_program_and_log_output(tmp, FALSE);
2569    mr_free(tmp);
2570
2571    mr_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2572    chdir(bkpinfo->restore_path);
2573    /* BERLIOS: should test return value, or better change the function */
2574    getcwd(newpath, MAX_STR_LEN - 1);
2575    mr_msg(1, "path is now %s", newpath);
2576    mr_msg(1, "restoring everything");
2577    if (!find_home_of_exe("petris") && !g_text_mode) {
2578        newtDrawRootText(0, g_noof_rows - 2,
2579                         _("Press ALT-<left cursor> twice to play Petris :-) "));
2580        newtRefresh();
2581    }
2582    mvaddstr_and_log_it(g_currentY, 0, _("Preparing to read your archives"));
2583    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2584        mount_cdrom(bkpinfo);
2585        mvaddstr_and_log_it(g_currentY++, 0,
2586                            _("Restoring OS and data from streaming media"));
2587        if (bkpinfo->backup_media_type == cdstream) {
2588            openin_cdstream(bkpinfo);
2589        } else {
2590            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->
2591                                                         media_device);
2592            openin_tape(bkpinfo);
2593        }
2594        resA = restore_all_tarballs_from_stream(bkpinfo, filelist);
2595        resB = restore_all_biggiefiles_from_stream(bkpinfo, filelist);
2596        if (bkpinfo->backup_media_type == cdstream) {
2597            closein_cdstream(bkpinfo);
2598        } else {
2599            closein_tape(bkpinfo);
2600        }
2601    } else {
2602        mvaddstr_and_log_it(g_currentY++, 0,
2603                            _("Restoring OS and data from CD       "));
2604        mount_cdrom(bkpinfo);
2605        resA = restore_all_tarballs_from_CD(bkpinfo, filelist);
2606        resB = restore_all_biggiefiles_from_CD(bkpinfo, filelist);
2607    }
2608    chdir(cwd);
2609    if (resA + resB) {
2610        log_to_screen(_("Errors occurred while data was being restored."));
2611    }
2612    if (length_of_file("/etc/raidtab") > 0) {
2613        mr_msg(2, "Copying local raidtab to restored filesystem");
2614        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2615                                   "/etc/raidtab", FALSE);
2616    }
2617    kill_petris();
2618    mr_msg(2, "restore_everything() --- leaving");
2619    mr_free(cwd);
2620    mr_free(newpath);
2621    return (resA + resB);
2622}
2623
2624/**************************************************************************
2625 *END_RESTORE_EVERYTHING                                                  *
2626 **************************************************************************/
2627
2628
2629/**
2630 * @brief Haha. You wish! (This function is not implemented :-)
2631 */
2632int
2633restore_live_from_monitas_server(struct s_bkpinfo *bkpinfo,
2634                                 char *monitas_device,
2635                                 char *restore_this_directory,
2636                                 char *restore_here)
2637     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2638{
2639    FILE *fout;
2640    int retval = 0;
2641    int i;
2642    int j;
2643    struct mountlist_itself the_mountlist;
2644    static struct raidlist_itself the_raidlist;
2645  /** malloc **/
2646    char tmp[MAX_STR_LEN + 1];
2647    char command[MAX_STR_LEN + 1];
2648    char datablock[256 * 1024];
2649    char datadisks_fname[MAX_STR_LEN + 1];
2650    long k;
2651    long length;
2652    long long llt;
2653    struct s_node *filelist = NULL;
2654    assert(bkpinfo != NULL);
2655    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2656    assert(restore_this_directory != NULL);
2657    assert(restore_here != NULL);
2658
2659    sprintf(tmp, "restore_here = '%s'", restore_here);
2660
2661    mr_msg(2, tmp);
2662
2663    mr_msg(2, "restore_live_from_monitas_server() - starting");
2664    unlink("/tmp/mountlist.txt");
2665    unlink("/tmp/filelist.full");
2666    unlink("/tmp/biggielist.txt");
2667    if (restore_here[0] == '\0') {
2668        strcpy(bkpinfo->restore_path, MNT_RESTORING);
2669    } else {
2670        strcpy(bkpinfo->restore_path, restore_here);
2671    }
2672    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2673    sprintf(tmp, "FYI - data will be restored to %s",
2674            bkpinfo->restore_path);
2675    mr_msg(3, tmp);
2676    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2677    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2678            (int) (random() % 32768));
2679    chdir(bkpinfo->tmpdir);
2680
2681    sprintf(command, "cat %s", monitas_device);
2682    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
2683    if (!(fout = fopen(datadisks_fname, "w"))) {
2684        log_OS_error(datadisks_fname);
2685        return (1);
2686    }
2687    for (i = 0; i < 32; i++) {
2688        for (j = 0; j < 4; j++) {
2689            for (length = k = 0; length < 256 * 1024; length += k) {
2690                k = fread(datablock + length, 1, 256 * 1024 - length,
2691                          g_tape_stream);
2692            }
2693            fwrite(datablock, 1, length, fout);
2694            g_tape_posK += length;
2695        }
2696    }
2697    paranoid_fclose(fout);
2698    sprintf(command,
2699            "tar -zxvf %s tmp/mondo-restore.cfg tmp/mountlist.txt tmp/filelist.full tmp/biggielist.txt",
2700            datadisks_fname);
2701    run_program_and_log_output(command, 4);
2702    read_header_block_from_stream(&llt, tmp, &i);
2703    read_header_block_from_stream(&llt, tmp, &i);
2704
2705    unlink(datadisks_fname);
2706    read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
2707    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
2708
2709
2710    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2711    iamhere("FIXME");
2712    fatal_error("This will fail");
2713    sprintf(command,
2714            "grep -E '^%s.*$' %s > %s",
2715            restore_this_directory, g_filelist_full, g_filelist_full);
2716    if (system(command)) {
2717        retval++;
2718        log_to_screen
2719            ("Error(s) occurred while processing filelist and wildcard");
2720    }
2721    iamhere("FIXME");
2722    fatal_error("This will fail");
2723    sprintf(command,
2724            "grep -E '^%s.*$' %s > %s",
2725            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2726    if (system(command)) {
2727        mr_msg(1,
2728                "Error(s) occurred while processing biggielist and wildcard");
2729    }
2730    sprintf(command, "touch %s", g_biggielist_txt);
2731    run_program_and_log_output(command, FALSE);
2732//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2733    retval += restore_everything(bkpinfo, filelist);
2734    free_filelist(filelist);
2735    mr_msg(2, "--------End of restore_live_from_monitas_server--------");
2736    return (retval);
2737}
2738
2739/**************************************************************************
2740 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
2741 **************************************************************************/
2742
2743
2744
2745
2746extern void wait_until_software_raids_are_prepped(int);
2747
2748char which_restore_mode(void);
2749
2750
2751/**
2752 * Log a "don't panic" message to the logfile.
2753 */
2754void welcome_to_mondorestore(void)
2755{
2756    mr_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2757    mr_msg(0,
2758            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2759    mr_msg(0,
2760            "don't break out in a cold sweat just because you see a few  ");
2761    mr_msg(0,
2762            "error messages in the log. Read them; analyze them; see if  ");
2763    mr_msg(0,
2764            "they are significant; above all, verify your backups! Please");
2765    mr_msg(0,
2766            "attach a compressed copy of this log to any e-mail you send ");
2767    mr_msg(0,
2768            "to the Mondo mailing list when you are seeking technical    ");
2769    mr_msg(0,
2770            "support. Without it, we can't help you.            - DevTeam");
2771    mr_msg(0,
2772            "------------------------------------------------------------");
2773    mr_msg(0,
2774            "BTW, despite (or perhaps because of) the wealth of messages,");
2775    mr_msg(0,
2776            "some users are inclined to stop reading this log.  If Mondo ");
2777    mr_msg(0,
2778            "stopped for some reason, chances are it's detailed here.    ");
2779    mr_msg(0,
2780            "More than likely there's a message near the end of this     ");
2781    mr_msg(0,
2782            "log that will tell you what is wrong.  Please read it!      ");
2783    mr_msg(0,
2784            "------------------------------------------------------------");
2785}
2786
2787
2788/**
2789 * Restore the user's data.
2790 * What did you think it did, anyway? :-)
2791 */
2792int main(int argc, char *argv[])
2793{
2794    FILE *fin = NULL;
2795    FILE *fout = NULL;
2796    int retval = 0;
2797    int res = 0;
2798    char *tmp = NULL;
2799
2800    struct mountlist_itself *mountlist = NULL;
2801    struct raidlist_itself *raidlist = NULL;
2802    struct s_bkpinfo *bkpinfo = NULL;
2803    struct s_node *filelist = NULL;
2804    char *a = NULL, *b = NULL;
2805    bool run_postnuke = FALSE;
2806
2807#ifdef ENABLE_NLS
2808    setlocale(LC_ALL, "");
2809    (void) textdomain("mondo");
2810#endif
2811
2812    /* Reference the right cleanup function for mr_exit */
2813    mr_cleanup = &mr_rs_cleanup;
2814
2815    if (getuid() != 0) {
2816        fprintf(stderr, _("Please run as root.\n"));
2817        mr_exit(127, NULL);
2818    }
2819
2820    g_loglevel = DEFAULT_MR_LOGLEVEL;
2821
2822/* Configure global variables */
2823#ifdef __FreeBSD__
2824    if (strstr
2825        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2826         "textonly"))
2827#else
2828    if (strstr
2829        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2830         "textonly"))
2831#endif
2832    {
2833        g_text_mode = TRUE;
2834        mr_msg(1, "TEXTONLY MODE");
2835    } else {
2836        g_text_mode = FALSE;
2837    }                           // newt :-)
2838    bkpinfo = mr_malloc(sizeof(struct s_bkpinfo));
2839    mountlist = mr_malloc(sizeof(struct mountlist_itself));
2840    raidlist = mr_malloc(sizeof(struct raidlist_itself));
2841
2842    malloc_libmondo_global_strings();
2843
2844    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2845    make_hole_for_dir(g_tmpfs_mountpt);
2846    g_current_media_number = 1; // precaution
2847
2848    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2849
2850    malloc_string(a);
2851    malloc_string(b);
2852    setup_MR_global_filenames(bkpinfo); // malloc() and set globals, using bkpinfo->tmpdir etc.
2853    reset_bkpinfo(bkpinfo);
2854    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2855    strcpy(bkpinfo->backup_media_string,"");
2856    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2857    if (am_I_in_disaster_recovery_mode()) {
2858        run_program_and_log_output("mount / -o remount,rw", 2);
2859    }                           // for b0rken distros
2860    g_main_pid = getpid();
2861    srandom((int) (time(NULL)));
2862    register_pid(getpid(), "mondo");
2863    set_signals(TRUE);
2864    g_kernel_version = get_kernel_version();
2865
2866    mr_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2867    if (strlen(g_mountlist_fname) < 3) {
2868        fatal_error
2869            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2870    }
2871    mkdir(MNT_CDROM, 0x770);
2872
2873/* Backup original mountlist.txt */
2874    mr_asprintf(&tmp, "%s.orig", g_mountlist_fname);
2875    if (!does_file_exist(g_mountlist_fname)) {
2876        mr_msg(2,
2877                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2878                __LINE__, g_mountlist_fname);
2879    } else if (!does_file_exist(tmp)) {
2880        mr_free(tmp);
2881        mr_asprintf(&tmp, "cp -f %s %s.orig", g_mountlist_fname,
2882                g_mountlist_fname);
2883        run_program_and_log_output(tmp, FALSE);
2884    }
2885    mr_free(tmp);
2886
2887/* Init directories */
2888    make_hole_for_dir(bkpinfo->tmpdir);
2889    mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->tmpdir);
2890    run_program_and_log_output(tmp, FALSE);
2891    mr_free(tmp);
2892
2893    make_hole_for_dir("/var/log");
2894    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
2895    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2896
2897    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2898
2899    /* Init GUI */
2900    malloc_libmondo_global_strings();
2901    setup_newt_stuff();         /* call newtInit and setup screen log */
2902    welcome_to_mondorestore();
2903    if (bkpinfo->disaster_recovery) {
2904        mr_msg(1, "I am in disaster recovery mode");
2905    } else {
2906        mr_msg(1, "I am in normal, live mode");
2907    }
2908
2909    iamhere("what time is it");
2910
2911    /* Process command-line parameters */
2912    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
2913#ifdef __FreeBSD__
2914        system("mv -f /tmp/raidconf.txt /etc/raidtab");
2915        if (!does_file_exist("/etc/raidtab"))
2916            system("vinum printconfig > /etc/raidtab");
2917#endif
2918        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2919        if (!does_file_exist(g_mountlist_fname)) {
2920            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2921        }
2922        res = let_user_edit_the_mountlist(bkpinfo, mountlist, raidlist);
2923#ifdef __FreeBSD__
2924        system("mv -f /etc/raidtab /tmp/raidconf.txt");
2925#endif
2926        paranoid_MR_finish(res);
2927    }
2928
2929    g_loglevel = DEFAULT_MR_LOGLEVEL;
2930    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
2931        fout = fopen("/tmp/out.txt", "w");
2932        fput_string_one_char_at_a_time(stderr, argv[2]);
2933        finish(0);
2934    }
2935
2936    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
2937        make_grub_install_scriptlet(argv[2]);
2938        finish(0);
2939    }
2940
2941    if (argc >= 2 && strcmp(argv[1], "--pih") == 0) {
2942        if (system("mount | grep cdrom 2> /dev/null > /dev/null")) {
2943            system("mount " MNT_CDROM);
2944        }
2945        bkpinfo->compression_level = 1;
2946        g_current_media_number = 2;
2947        strcpy(bkpinfo->restore_path, "/tmp/TESTING");
2948        bkpinfo->backup_media_type = dvd;
2949        open_progress_form(_("Reassembling /dev/hda1"),
2950                           _("Shark is a bit of a silly person."),
2951                           _("Please wait. This may take some time."),
2952                           "", 1999);
2953        system("rm -Rf /tmp/*pih*");
2954
2955        malloc_string(tmp);
2956        restore_a_biggiefile_from_CD(bkpinfo, 42, NULL, tmp);
2957        mr_free(tmp);
2958    }
2959
2960    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
2961        g_loglevel = 6;
2962        filelist = load_filelist(argv[2]);
2963        if (!filelist) {
2964            fatal_error("Failed to load filelist");
2965        }
2966        toggle_node_selection(filelist, FALSE);
2967        toggle_all_root_dirs_on(filelist);
2968        // BERLIOS: /usr/lib ???
2969        toggle_path_selection(filelist, "/usr/share", TRUE);
2970        save_filelist(filelist, "/tmp/out.txt");
2971        mr_asprintf(&a, argv[3]);
2972        mr_asprintf(&b, argv[4]);
2973
2974        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
2975        free_filelist(filelist);
2976        mr_free(a);
2977        mr_free(b);
2978        printf("res = %d", res);
2979        finish(0);
2980    }
2981
2982    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
2983        popup_changelist_from_file(argv[2]);
2984        paranoid_MR_finish(0);
2985    }
2986
2987    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
2988        mr_msg(1, "SCORE");
2989        g_loglevel = 10;
2990        if (strstr(argv[2], "save")) {
2991            mr_msg(1, "Saving from %s to %s", argv[3], argv[4]);
2992            fin = fopen(argv[3], "r");
2993            fout = fopen(argv[4], "w");
2994            copy_from_src_to_dest(fin, fout, 'w');
2995            fclose(fin);
2996            fin = fopen(argv[3], "r");
2997            copy_from_src_to_dest(fin, fout, 'w');
2998            fclose(fout);
2999            fclose(fin);
3000        } else if (strstr(argv[2], "restore")) {
3001            fout = fopen(argv[3], "w");
3002            fin = fopen(argv[4], "r");
3003            copy_from_src_to_dest(fout, fin, 'r');
3004            fclose(fin);
3005            fin = fopen(argv[4], "r");
3006            copy_from_src_to_dest(fout, fin, 'r');
3007            fclose(fout);
3008            fclose(fin);
3009        } else {
3010            fatal_error("Unknown additional param");
3011        }
3012        finish(0);
3013    }
3014
3015    if (argc == 2 && strcmp(argv[1], "--mdstat") == 0) {
3016        wait_until_software_raids_are_prepped(100);
3017        finish(0);
3018    }
3019
3020    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
3021        finish(create_raidtab_from_mdstat(argv[2]));
3022    }
3023
3024    if (argc == 3 && strcmp(argv[1], "-p") == 0) {
3025        strcpy(bkpinfo->prefix,argv[2]);
3026        mr_msg(1,"Prefix forced to %s",bkpinfo->prefix);
3027    }
3028
3029
3030    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
3031        retval = run_grub(FALSE, "/dev/hda");
3032        if (retval) {
3033            log_to_screen(_("Failed to write Master Boot Record"));
3034        }
3035        paranoid_MR_finish(0);
3036    }
3037    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
3038        g_current_media_number = atoi(argv[2]);
3039        pause_and_ask_for_cdr(5);
3040        paranoid_MR_finish(0);
3041    } else if (!bkpinfo->disaster_recovery) {   // live!
3042        if (argc != 1) {
3043            popup_and_OK
3044                (_("Live mode doesn't support command-line parameters yet."));
3045            paranoid_MR_finish(1);
3046        }
3047        mr_msg(1, "I am in normal, live mode.");
3048        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
3049        mount_boot_if_necessary();  /* for Gentoo users */
3050        mr_msg(2, "Still here.");
3051        if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
3052            g_restoring_live_from_cd = TRUE;
3053        }
3054        if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
3055            retval =
3056                restore_live_from_monitas_server(bkpinfo,
3057                                                 argv[2],
3058                                                 argv[3], argv[4]);
3059        } else {
3060            mr_msg(2, "Calling restore_to_live_filesystem()");
3061            retval = restore_to_live_filesystem(bkpinfo);
3062        }
3063        mr_msg(2, "Still here. Yay.");
3064        if (strlen(bkpinfo->tmpdir) > 0) {
3065            mr_asprintf(&tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3066            run_program_and_log_output(tmp, FALSE);
3067            mr_free(tmp);
3068        }
3069        unmount_boot_if_necessary();    /* for Gentoo users */
3070        paranoid_MR_finish(retval);
3071    } else {
3072        /* Disaster recovery mode (must be) */
3073        mr_msg(1, "I must be in disaster recovery mode.");
3074        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3075        if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
3076            log_to_screen(_("Uh, that hasn't been implemented yet."));
3077            paranoid_MR_finish(1);
3078        }
3079
3080        iamhere("About to call load_mountlist and load_raidtab");
3081        strcpy(bkpinfo->restore_path, MNT_RESTORING);
3082        read_cfg_file_into_bkpinfo(g_mondo_cfg_file, bkpinfo);
3083        retval = load_mountlist(mountlist, g_mountlist_fname);
3084        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3085        iamhere
3086            ("Returned from calling load_mountlist and load_raidtab successfully");
3087
3088        if (argc > 1
3089            && (strcmp(argv[1], "--compare") == 0
3090                || strcmp(argv[1], "--nuke") == 0)) {
3091            if (bkpinfo->backup_media_type == nfs
3092                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3093                mr_msg(1, "Mounting nfs dir");
3094                sprintf(bkpinfo->isodir, "/tmp/isodir");
3095                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3096                mr_asprintf(&tmp, "mount %s -t nfs -o nolock /tmp/isodir",
3097                        bkpinfo->nfs_mount);
3098                run_program_and_log_output(tmp, 1);
3099                mr_free(tmp);
3100            }
3101        }
3102
3103
3104        if (retval) {
3105            log_to_screen
3106                (_("Warning - load_raidtab_into_raidlist returned an error"));
3107        }
3108
3109
3110        mr_msg(1, "Send in the clowns.");
3111
3112        if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
3113            mr_msg(0, "Partitioning only.");
3114            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3115            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3116            load_mountlist(mountlist, g_mountlist_fname);
3117            res = partition_everything(mountlist);
3118            finish(res);
3119        }
3120
3121        if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3122            mr_msg(0, "Formatting only.");
3123            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3124            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3125            load_mountlist(mountlist, g_mountlist_fname);
3126            res = format_everything(mountlist, FALSE, raidlist);
3127            finish(res);
3128        }
3129
3130        if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3131            mr_msg(0, "Stopping LVM and RAID");
3132            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3133            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3134            load_mountlist(mountlist, g_mountlist_fname);
3135            res = do_my_funky_lvm_stuff(TRUE, FALSE);
3136            res += stop_all_raid_devices(mountlist);
3137            finish(res);
3138        }
3139
3140        if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3141            iamhere("nuking");
3142            retval += nuke_mode(bkpinfo, mountlist, raidlist);
3143        } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3144            iamhere("catchall");
3145            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3146        } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3147            iamhere("compare");
3148            retval += compare_mode(bkpinfo, mountlist, raidlist);
3149        } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3150            iamhere("iso");
3151            retval = iso_mode(bkpinfo, mountlist, raidlist, FALSE);
3152        } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3153            iamhere("mbr");
3154            retval = mount_all_devices(mountlist, TRUE);
3155            if (!retval) {
3156                retval += run_boot_loader(FALSE);
3157                retval += unmount_all_devices(mountlist);
3158            }
3159            if (retval) {
3160                log_to_screen(_("Failed to write Master Boot Record"));
3161            }
3162        } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3163            iamhere("isonuke");
3164            retval = iso_mode(bkpinfo, mountlist, raidlist, TRUE);
3165        } else if (argc != 1) {
3166            log_to_screen(_("Invalid parameters"));
3167            paranoid_MR_finish(1);
3168        } else {
3169            iamhere("catchall (no mode specified in command-line call");
3170            retval += catchall_mode(bkpinfo, mountlist, raidlist);
3171        }
3172    }
3173
3174    /* clean up at the end */
3175    if (retval) {
3176        if (does_file_exist("/tmp/changed.files")) {
3177            log_to_screen
3178                (_("See /tmp/changed.files for list of files that have changed."));
3179        }
3180        mvaddstr_and_log_it(g_currentY++,
3181                            0,
3182                            _("Run complete. Errors were reported. Please review the logfile."));
3183    } else {
3184        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3185            mvaddstr_and_log_it(g_currentY++,
3186                                0,
3187                                _("Run complete. Please remove CD/media and reboot."));
3188        } else {
3189            run_program_and_log_output("sync", FALSE);
3190            if (is_this_device_mounted(MNT_CDROM)) {
3191                res =
3192                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
3193            } else {
3194                res = 0;
3195            }
3196
3197            if (!bkpinfo->please_dont_eject) {
3198                res = eject_device("/dev/cdrom");
3199            }
3200            mvaddstr_and_log_it(g_currentY++,
3201                                0,
3202                                _("Run complete. Please remove media and reboot."));
3203        }
3204    }
3205
3206    // g_I_have_just_nuked is set true by nuke_mode() just before it returns
3207    if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3208      mr_msg(1, "post-nuke found; find out whether we should run it...");
3209      if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3210        run_postnuke = TRUE;
3211        mr_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3212      } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3213        run_postnuke = TRUE;
3214        mr_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3215      } else {
3216        run_postnuke = FALSE;
3217        mr_msg(1, "No, will not run post-nuke.");
3218      }
3219    } else {
3220      mr_msg(1, "No post-nuke found.");
3221    }
3222    if (run_postnuke) {
3223      log_to_screen("Running post-nuke...");
3224      if (mount_all_devices(mountlist, TRUE)) {
3225        log_to_screen
3226          ("Unable to re-mount partitions for post-nuke stuff");
3227      } else {
3228        mr_msg(1, "Re-mounted partitions for post-nuke stuff");
3229        mr_asprintf(&tmp, "post-nuke %s %d", bkpinfo->restore_path,
3230            retval);
3231        mr_msg(2, "Calling '%s'", tmp);
3232        if ((res = run_program_and_log_output(tmp, 0))) {
3233          log_OS_error(tmp);
3234        }
3235        mr_free(tmp);
3236        mr_msg(1, "post-nuke returned w/ res=%d", res);
3237      }
3238      unmount_all_devices(mountlist);
3239      log_to_screen("I've finished post-nuking.");
3240    }
3241
3242    unlink("/tmp/mondo-run-prog.tmp");
3243    set_signals(FALSE);
3244    mr_asprintf(&tmp, "rm -Rf %s", bkpinfo->tmpdir);
3245    run_program_and_log_output(tmp, FALSE);
3246    mr_free(tmp);
3247
3248    log_to_screen
3249        (_("Restore log (%s) copied to /var/log on your hard disk"), MONDO_LOGFILE);
3250    log_to_screen(_("Mondo-restore is exiting (retval=%d)"), retval);
3251
3252    mr_asprintf(&tmp, "umount %s", bkpinfo->isodir);
3253    run_program_and_log_output(tmp, 5);
3254    mr_free(tmp);
3255
3256    mr_free(mountlist);
3257    mr_free(raidlist);
3258    if (am_I_in_disaster_recovery_mode()) {
3259        run_program_and_log_output("mount / -o remount,rw", 2);
3260    }                           // for b0rken distros
3261    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3262    free_libmondo_global_strings(); // it's fine to have this here :) really :)
3263
3264    unlink("/tmp/filelist.full");
3265    unlink("/tmp/filelist.full.gz");
3266
3267    mr_exit(retval, NULL);
3268}
3269
3270/**************************************************************************
3271 *END_MAIN                                                                *
3272 **************************************************************************/
3273
3274
3275/**************************************************************************
3276 *END_MONDO-RESTORE.C                                                     *
3277 **************************************************************************/
Note: See TracBrowser for help on using the repository browser.