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

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

merge -r 1842:1889 2.2.5

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