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

Last change on this file since 1939 was 1939, checked in by Bruno Cornec, 12 years ago

svn merge -r 1923:1938 $SVN_M/branches/2.2.6

  • Property svn:keywords set to Id
File size: 198.8 KB
Line 
1/***************************************************************************
2* restores mondoarchive data
3* $Id: mondorestore.c 1939 2008-05-16 23:29:54Z 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 1939 2008-05-16 23:29:54Z 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 && !g_restoring_live_from_nfs) {
927        popup_and_OK
928            (_("Please insert tape/CD/USB key, then hit 'OK' to continue."));
929        sleep(1);
930    }
931    if (!g_restoring_live_from_nfs) {
932        interactively_obtain_media_parameters_from_user(FALSE);
933    }
934    if (!bkpinfo->media_device) {
935        mr_msg(2, "Warning - failed to find media dev");
936    } else {
937        mr_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
938    }
939
940
941    mr_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
942
943    open_evalcall_form(_("Thinking..."));
944
945    get_cfg_file_from_archive_or_bust();
946    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
947    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
948
949    close_evalcall_form();
950    retval = load_mountlist(mountlist, g_mountlist_fname);
951    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
952
953    if (!g_restoring_live_from_nfs && (filelist = process_filelist_and_biggielist())) {
954        save_filelist(filelist, "/tmp/selected-files.txt");
955        mr_asprintf(&old_restpath,bkpinfo->restore_path);
956        if (popup_and_get_string(_("Restore path"),
957                                 _("Restore files to where? "),
958                                 bkpinfo->restore_path, MAX_STR_LEN)) {
959            iamhere("Restoring everything");
960            retval += restore_everything(filelist);
961        }
962        free_filelist(filelist);
963        strcpy(bkpinfo->restore_path, old_restpath);
964        mr_free(old_restpath);
965    } else {
966        retval += restore_everything(NULL);
967    }
968    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
969        mr_msg(2,
970                "Tape : I don't need to unmount or eject the CD-ROM.");
971    } else {
972        run_program_and_log_output("umount " MNT_CDROM, FALSE);
973        if (!bkpinfo->please_dont_eject) {
974            eject_device(bkpinfo->media_device);
975        }
976    }
977    run_program_and_log_output("umount " MNT_CDROM, FALSE);
978    if ((!bkpinfo->please_dont_eject) && (bkpinfo->media_device)) {
979        eject_device(bkpinfo->media_device);
980    }
981    mr_free(mountlist);
982    mr_free(raidlist);
983    return (retval);
984}
985
986/**************************************************************************
987 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
988 **************************************************************************/
989
990/* @} - end of restoreGroup */
991
992
993/**
994 * @addtogroup LLrestoreGroup
995 * @{
996 */
997/**
998 * Restore biggiefile @p bigfileno from the currently mounted CD.
999 * @param bkpinfo The backup information structure. Fields used:
1000 * - @c bkpinfo->backup_media_type
1001 * - @c bkpinfo->restore_path
1002 * @param bigfileno The biggiefile number (starting from 0) to restore.
1003 * @param filelist The node structure containing the list of files to restore.
1004 * If the biggiefile is not in this list, it will be skipped (return value will
1005 * still indicate success).
1006 * @return 0 for success (or skip), nonzero for failure.
1007 */
1008int
1009restore_a_biggiefile_from_CD(long bigfileno,
1010                             struct s_node *filelist,
1011                             char *pathname_of_last_file_restored)
1012{
1013    FILE *fin = NULL;
1014    FILE *fout = NULL;
1015    FILE *fbzip2 = NULL;
1016
1017    char *checksum = NULL;
1018    char *outfile_fname = NULL;
1019    char *tmp = NULL;
1020    char *bzip2_command = NULL;
1021    char *suffix = NULL;
1022    char *bigblk = NULL;
1023    int retval = 0;
1024    int finished = FALSE;
1025    long sliceno = 0L;
1026    long siz;
1027    char *ntfsprog_fifo = NULL;
1028    char *file_to_openout = NULL;
1029    struct s_filename_and_lstat_info biggiestruct;
1030    struct utimbuf the_utime_buf, *ubuf = NULL;
1031    bool use_ntfsprog_hack = FALSE;
1032    pid_t pid;
1033    int res = 0;
1034    int old_loglevel;
1035    struct s_node *node = NULL;
1036
1037    old_loglevel = mr_conf->log_level;
1038    ubuf = &the_utime_buf;
1039    assert(bkpinfo != NULL);
1040
1041    pathname_of_last_file_restored[0] = '\0';
1042    bigblk = mr_malloc(mr_conf->external_tape_blocksize);
1043
1044    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1045        log_to_screen("Cannot even open bigfile's info file");
1046        return (1);
1047    }
1048
1049    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1050    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1051        sizeof(biggiestruct)) {
1052        mr_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1053                bigfileno + 1);
1054    }
1055    paranoid_fclose(fin);
1056
1057    mr_asprintf(&checksum, biggiestruct.checksum);
1058
1059    if (!checksum[0]) {
1060        mr_msg(3, "Warning - bigfile %ld does not have a checksum",
1061                bigfileno + 1);
1062    }
1063    mr_free(checksum);
1064
1065    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
1066    {
1067        mr_asprintf(&outfile_fname, biggiestruct.filename);
1068    } else {
1069        mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
1070                biggiestruct.filename);
1071    }
1072
1073    /* skip file if we have a selective restore subset & it doesn't match */
1074    if (filelist != NULL) {
1075        node = find_string_at_node(filelist, biggiestruct.filename);
1076        if (!node) {
1077            mr_msg(0, "Skipping %s (name isn't in filelist)",
1078                    biggiestruct.filename);
1079            return (0);
1080        } else if (!(node->selected)) {
1081            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
1082                    biggiestruct.filename);
1083            return (0);
1084        }
1085    }
1086    /* otherwise, continue */
1087
1088    mr_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1089    if (biggiestruct.use_ntfsprog) {
1090        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1091            mr_msg(1,
1092                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1093            mr_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1094            biggiestruct.use_ntfsprog = FALSE;
1095        }
1096    }
1097
1098    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
1099    {
1100        mr_conf->log_level = 4;
1101        use_ntfsprog_hack = TRUE;
1102        mr_msg(2,
1103                "Calling ntfsclone in background because %s is an NTFS /dev entry",
1104                outfile_fname);
1105        mr_asprintf(&ntfsprog_fifo, "/tmp/%d.%d.000", (int) (random() % 32768),
1106                (int) (random() % 32768));
1107        mkfifo(ntfsprog_fifo, 0x770);
1108
1109        file_to_openout = ntfsprog_fifo;
1110        switch (pid = fork()) {
1111        case -1:
1112            fatal_error("Fork failure");
1113        case 0:
1114            mr_msg(3,
1115                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1116                    biggiestruct.filename, ntfsprog_fifo);
1117            res =
1118                feed_outfrom_ntfsprog(biggiestruct.filename,
1119                                      ntfsprog_fifo);
1120            exit(res);
1121            break;
1122        default:
1123            mr_msg(3,
1124                    "feed_into_ntfsprog() called in background --- pid=%ld",
1125                    (long int) (pid));
1126        }
1127    } else {
1128        use_ntfsprog_hack = FALSE;
1129        file_to_openout = outfile_fname;
1130        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1131        {
1132            make_hole_for_file(outfile_fname);
1133        }
1134    }
1135
1136    mr_msg(2, "Reassembling big file %ld (%s)", bigfileno + 1,
1137            outfile_fname);
1138
1139    /*
1140       last slice is zero-length and uncompressed; when we find it, we stop.
1141       We DON'T wait until there are no more slices; if we did that,
1142       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1143     */
1144
1145    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1146            MAX_STR_LEN - 1);
1147    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1148
1149    mr_msg(3, "file_to_openout = %s", file_to_openout);
1150    if (!(fout = fopen(file_to_openout, "w"))) {
1151        log_to_screen(_("Cannot openout file_to_openout - hard disk full?"));
1152        return (1);
1153    }
1154
1155    mr_free(ntfsprog_fifo);
1156    mr_msg(3, "Opened out to %s", outfile_fname);   // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1157
1158    for (sliceno = 1, finished = FALSE; !finished;) {
1159        if (!does_file_exist
1160            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1161            &&
1162            !does_file_exist(slice_fname
1163                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1164            &&
1165            !does_file_exist(slice_fname
1166                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1167            &&
1168            !does_file_exist(slice_fname
1169                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1170            mr_msg(3,
1171                    "Cannot find a data slice or terminator slice on CD %d",
1172                    g_current_media_number);
1173            g_current_media_number++;
1174            mr_msg(2, "Asking for %s #%d so that I may read slice #%ld\n",
1175                    media_descriptor_string(bkpinfo->backup_media_type),
1176                    g_current_media_number, sliceno);
1177            log_to_screen(_("Restoring from %s #%d"),
1178                    bkpinfo->backup_media_string,
1179                    g_current_media_number);
1180            insist_on_this_cd_number(g_current_media_number);
1181            log_to_screen(_("Continuing to restore."));
1182        } else {
1183            mr_asprintf(&tmp,
1184                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1185            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1186                mr_msg(2,
1187                        "End of bigfile # %ld (slice %ld is the terminator)",
1188                        bigfileno + 1, sliceno);
1189                finished = TRUE;
1190                mr_free(tmp);
1191                continue;
1192            } else {
1193                mr_free(tmp);
1194                if (does_file_exist
1195                    (slice_fname
1196                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1197                    mr_asprintf(&bzip2_command, "lzop");
1198                    mr_asprintf(&suffix, "lzo");
1199                } else
1200                    if (does_file_exist
1201                        (slice_fname
1202                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1203                    mr_asprintf(&bzip2_command, "gzip");
1204                    mr_asprintf(&suffix, "gz");
1205                } else
1206                    if (does_file_exist
1207                        (slice_fname
1208                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1209                    mr_asprintf(&bzip2_command, "bzip2");
1210                    mr_asprintf(&suffix, "bz2");
1211                } else
1212                    if (does_file_exist
1213                        (slice_fname
1214                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1215                    mr_asprintf(&bzip2_command, "");
1216                    mr_asprintf(&suffix, "");
1217                } else {
1218                    log_to_screen(_("OK, that's pretty fsck0red..."));
1219                    return (1);
1220                }
1221            }
1222            if (bzip2_command[0] != '\0') {
1223                mr_strcat(bzip2_command,
1224                        " -dc %s 2>> %s",
1225                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1226                                    suffix), MONDO_LOGFILE);
1227            } else {
1228                mr_free(bzip2_command);
1229                mr_asprintf(&bzip2_command, "cat %s 2>> %s",
1230                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1231                                    suffix), MONDO_LOGFILE);
1232            }
1233            mr_asprintf(&tmp, "Working on %s #%d, file #%ld, slice #%ld",
1234                    bkpinfo->backup_media_string,
1235                    g_current_media_number, bigfileno + 1, sliceno);
1236            mr_msg(2, tmp);
1237            if (!g_text_mode) {
1238                newtDrawRootText(0, g_noof_rows - 2, tmp);
1239                newtRefresh();
1240                update_progress_form(tmp);
1241            }
1242            mr_free(tmp);
1243
1244            if (!(fbzip2 = popen(bzip2_command, "r"))) {
1245                mr_free(bzip2_command);
1246                mr_free(suffix);
1247                fatal_error("Can't run popen command");
1248            }
1249            mr_free(bzip2_command);
1250            mr_free(suffix);
1251
1252            while (!feof(fbzip2)) {
1253                siz = fread(bigblk, 1, mr_conf->external_tape_blocksize, fbzip2);
1254                if (siz > 0) {
1255                    siz = fwrite(bigblk, 1, siz, fout);
1256                }
1257            }
1258            paranoid_pclose(fbzip2);
1259
1260            sliceno++;
1261            g_current_progress++;
1262        }
1263    }
1264    paranoid_fclose(fout);
1265    mr_conf->log_level = old_loglevel;
1266
1267    if (use_ntfsprog_hack) {
1268        mr_msg(3, "Waiting for ntfsclone to finish");
1269        mr_asprintf(&tmp,
1270                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1271        while (system(tmp) == 0) {
1272            sleep(1);
1273        }
1274        mr_free(tmp);
1275        log_it("OK, ntfsclone has really finished");
1276    }
1277
1278    if (strcmp(outfile_fname, "/dev/null")) {
1279        chown(outfile_fname, biggiestruct.properties.st_uid,
1280              biggiestruct.properties.st_gid);
1281        chmod(outfile_fname, biggiestruct.properties.st_mode);
1282        ubuf->actime = biggiestruct.properties.st_atime;
1283        ubuf->modtime = biggiestruct.properties.st_mtime;
1284        utime(outfile_fname, ubuf);
1285    }
1286    mr_free(outfile_fname);
1287    mr_free(bigblk);
1288
1289    return (retval);
1290}
1291
1292
1293/**************************************************************************
1294 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
1295 **************************************************************************/
1296
1297
1298/**
1299 * Restore a biggiefile from the currently opened stream.
1300 * @param bkpinfo The backup information structure. Fields used:
1301 * - @c bkpinfo->restore_path
1302 * - @c bkpinfo->compression_tool
1303 * @param orig_bf_fname The original filename of the biggiefile.
1304 * @param biggiefile_number The number of the biggiefile (starting from 0).
1305 * @param filelist The node structure containing the list of files to be restored.
1306 * If @p orig_bf_fname is not in the list, it will be ignored.
1307 * @return 0 for success (or skip), nonzero for failure.
1308 */
1309int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
1310                                     long long biggiefile_size, //UNUSED
1311                                     struct s_node *filelist,
1312                                     int use_ntfsprog,
1313                                     char *pathname_of_last_file_restored)
1314{
1315    FILE *pout = NULL;
1316    FILE *fin = NULL;
1317
1318  /** mallocs ********/
1319    char *tmp = NULL;
1320    char *tmp1 = NULL;
1321    char *command = NULL;
1322    char *outfile_fname = NULL;
1323    char *ntfsprog_fifo = NULL;
1324    char *file_to_openout = NULL;
1325
1326    struct s_node *node = NULL;
1327
1328    int old_loglevel = 0;
1329    long current_slice_number = 0;
1330    int retval = 0;
1331    int res = 0;
1332    int ctrl_chr = '\0';
1333    long long slice_siz = 0L;
1334    bool dummy_restore = FALSE;
1335    bool use_ntfsprog_hack = FALSE;
1336    pid_t pid;
1337    struct s_filename_and_lstat_info biggiestruct;
1338    struct utimbuf the_utime_buf, *ubuf = NULL;
1339    ubuf = &the_utime_buf;
1340
1341    old_loglevel = mr_conf->log_level;
1342    assert(bkpinfo != NULL);
1343    assert(orig_bf_fname != NULL);
1344    assert(orig_checksum != NULL);
1345
1346    pathname_of_last_file_restored[0] = '\0';
1347    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1348        use_ntfsprog = 1;
1349        mr_msg(1, "%s --- pih=YES", orig_bf_fname);
1350    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1351        use_ntfsprog = 0;
1352        mr_msg(1, "%s --- pih=NO", orig_bf_fname);
1353    } else {
1354        use_ntfsprog = 0;
1355        mr_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1356    }
1357
1358    strncpy(pathname_of_last_file_restored, orig_bf_fname,
1359            MAX_STR_LEN - 1);
1360    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1361
1362    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1363
1364    if (filelist != NULL) {
1365        node = find_string_at_node(filelist, orig_bf_fname);
1366        if (!node) {
1367            dummy_restore = TRUE;
1368            mr_msg(1,
1369                    "Skipping big file %ld (%s) - not in biggielist subset",
1370                    biggiefile_number + 1, orig_bf_fname);
1371            pathname_of_last_file_restored[0] = '\0';
1372        } else if (!(node->selected)) {
1373            dummy_restore = TRUE;
1374            mr_msg(1, "Skipping %s (name isn't in biggielist subset)",
1375                    orig_bf_fname);
1376            pathname_of_last_file_restored[0] = '\0';
1377        }
1378    }
1379
1380    if (use_ntfsprog) {
1381        if (strncmp(orig_bf_fname, "/dev/", 5)) {
1382            mr_msg(1, "I was in error when I set use_ntfsprog to TRUE.");
1383            mr_msg(1, "%s isn't even in /dev", orig_bf_fname);
1384            use_ntfsprog = FALSE;
1385        }
1386    }
1387
1388    if (use_ntfsprog) {
1389        mr_conf->log_level = 4;
1390        mr_asprintf(&outfile_fname, orig_bf_fname);
1391        use_ntfsprog_hack = TRUE;
1392        mr_msg(2,
1393                "Calling ntfsclone in background because %s is a /dev entry",
1394                outfile_fname);
1395        mr_asprintf(&ntfsprog_fifo, "%s/%d.%d.000", 
1396                bkpinfo->tmpdir,
1397                (int) (random() % 32768),
1398                (int) (random() % 32768));
1399        mkfifo(ntfsprog_fifo, 0x770);
1400
1401        file_to_openout = ntfsprog_fifo;
1402        switch (pid = fork()) {
1403        case -1:
1404            fatal_error("Fork failure");
1405        case 0:
1406            mr_msg(3,
1407                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1408                    outfile_fname, ntfsprog_fifo);
1409            res = feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1410            exit(res);
1411            break;
1412        default:
1413            mr_msg(3,
1414                    "feed_into_ntfsprog() called in background --- pid=%ld",
1415                    (long int) (pid));
1416        }
1417    } else {
1418        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
1419        {
1420            mr_asprintf(&outfile_fname, orig_bf_fname);
1421        } else                  // biggiefile
1422        {
1423            mr_asprintf(&outfile_fname, "%s/%s", bkpinfo->restore_path,
1424                    orig_bf_fname);
1425        }
1426        use_ntfsprog_hack = FALSE;
1427        file_to_openout = outfile_fname;
1428        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1429        {
1430            make_hole_for_file(outfile_fname);
1431        }
1432        mr_msg(2, "Reassembling big file %ld (%s)",
1433                biggiefile_number + 1, orig_bf_fname);
1434    }
1435
1436    if (dummy_restore) {
1437        mr_free(outfile_fname);
1438        mr_asprintf(&outfile_fname, "/dev/null");
1439    }
1440
1441    if (!bkpinfo->compression_tool) {
1442        mr_asprintf(&command, "cat > \"%s\"", file_to_openout);
1443    } else {
1444        mr_asprintf(&command, "%s -dc > \"%s\" 2>> %s", bkpinfo->compression_tool,
1445                file_to_openout, MONDO_LOGFILE);
1446    }
1447    mr_msg(3, "Pipe command = '%s'", command);
1448    mr_free(outfile_fname);
1449    mr_free(ntfsprog_fifo);
1450
1451    /* restore biggiefile, one slice at a time */
1452    if (!(pout = popen(command, "w"))) {
1453        fatal_error("Cannot pipe out");
1454    }
1455    mr_free(command);
1456
1457    malloc_string(tmp1);
1458    for (res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1459         ctrl_chr != BLK_STOP_A_BIGGIE;
1460         res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr)) {
1461        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1462            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1463        }
1464        mr_asprintf(&tmp, "Working on file #%ld, slice #%ld    ",
1465                biggiefile_number + 1, current_slice_number);
1466        mr_msg(2, tmp);
1467        if (!g_text_mode) {
1468            newtDrawRootText(0, g_noof_rows - 2, tmp);
1469            newtRefresh();
1470        }
1471        mr_strip_spaces(tmp);
1472        update_progress_form(tmp);
1473        mr_free(tmp);
1474        if (current_slice_number == 0) {
1475            res =
1476                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
1477                                              slice_siz);
1478            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1479                log_OS_error("blah blah");
1480            } else {
1481                if (fread
1482                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1483                     fin) < sizeof(biggiestruct)) {
1484                    mr_msg(2,
1485                            "Warning - unable to get biggiestruct of bigfile #%d",
1486                            biggiefile_number + 1);
1487                }
1488                paranoid_fclose(fin);
1489            }
1490        } else {
1491            res =
1492                read_file_from_stream_to_stream(pout, slice_siz);
1493        }
1494        retval += res;
1495        res = read_header_block_from_stream(&slice_siz, tmp1, &ctrl_chr);
1496        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1497            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1498        }
1499        current_slice_number++;
1500        g_current_progress++;
1501    }
1502    mr_free(tmp1);
1503    paranoid_pclose(pout);
1504
1505    mr_msg(1, "pathname_of_last_file_restored is now %s",
1506            pathname_of_last_file_restored);
1507
1508    if (use_ntfsprog_hack) {
1509        mr_msg(3, "Waiting for ntfsclone to finish");
1510        mr_asprintf(&tmp,
1511                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1512        while (system(tmp) == 0) {
1513            sleep(1);
1514        }   
1515        mr_free(tmp);
1516        mr_msg(3, "OK, ntfsclone has really finished");
1517    }
1518
1519    mr_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1520    mr_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1521    if (strcmp(outfile_fname, "/dev/null")) {
1522        chmod(outfile_fname, biggiestruct.properties.st_mode);
1523        chown(outfile_fname, biggiestruct.properties.st_uid,
1524              biggiestruct.properties.st_gid);
1525        ubuf->actime = biggiestruct.properties.st_atime;
1526        ubuf->modtime = biggiestruct.properties.st_mtime;
1527        utime(outfile_fname, ubuf);
1528    }
1529
1530    mr_conf->log_level = old_loglevel;
1531    return (retval);
1532}
1533
1534/**************************************************************************
1535 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
1536 **************************************************************************/
1537
1538
1539/**
1540 * Restore @p tarball_fname from CD.
1541 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1542 * This will be used unmodified.
1543 * @param current_tarball_number The number (starting from 0) of the fileset
1544 * we're restoring now.
1545 * @param filelist The node structure containing the list of files to be
1546 * restored. If no file in the afioball is in this list, afio will still be
1547 * called, but nothing will be written.
1548 * @return 0 for success, nonzero for failure.
1549 */
1550int
1551restore_a_tarball_from_CD(char *tarball_fname,
1552                          long current_tarball_number,
1553                          struct s_node *filelist, struct s_bkpinfo *bkpinfo)
1554{
1555    int retval = 0;
1556    int res = 0;
1557    char *p = NULL;
1558
1559  /** malloc **/
1560    char *command = NULL;
1561    char *tmp = NULL;
1562    char *filelist_name = NULL;
1563    char *filelist_subset_fname = NULL;
1564    char *executable = NULL;
1565    char *temp_log = NULL;
1566    long matches = 0;
1567    bool use_star = FALSE;
1568    char *xattr_fname = NULL;
1569    char *acl_fname = NULL;
1570#ifdef __FreeBSD__
1571    long BUFSIZE=512L;
1572#else
1573    long BUFSIZE=(1024L*1024L)/mr_conf->external_tape_blocksize;
1574#endif
1575
1576
1577    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1578
1579    mr_msg(5, "Entering");
1580    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1581    mr_asprintf(&command, "mkdir -p %s/tmp", MNT_RESTORING);
1582    run_program_and_log_output(command, 9);
1583    mr_free(command);
1584
1585    mr_asprintf(&filelist_name, MNT_CDROM "/archives/filelist.%ld",
1586            current_tarball_number);
1587    if (length_of_file(filelist_name) <= 2) {
1588        mr_msg(2, "There are _zero_ files in filelist '%s'",
1589                filelist_name);
1590        mr_msg(2,
1591                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1592        mr_msg(2,
1593                "but it's non-critical. It's cosmetic. Don't worry about it.");
1594        retval = 0;
1595        mr_msg(5, "Leaving");
1596        mr_free(filelist_name);
1597        return (retval);
1598    }
1599    if (count_lines_in_file(filelist_name) <= 0
1600        || length_of_file(tarball_fname) <= 0) {
1601        mr_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1602                length_of_file(tarball_fname));
1603        log_to_screen(_("Unable to restore fileset #%ld (CD I/O error)"),
1604                current_tarball_number);
1605        retval = 1;
1606        mr_msg(5, "Leaving");
1607        mr_free(filelist_name);
1608        return (retval);
1609    }
1610
1611    if (filelist) {
1612        mr_asprintf(&filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1613                current_tarball_number);
1614        if ((matches =
1615             save_filelist_entries_in_common(filelist_name, filelist,
1616                                             filelist_subset_fname,
1617                                             use_star))
1618            <= 0) {
1619            mr_msg(1, "Skipping fileset %ld", current_tarball_number);
1620        } else {
1621            mr_msg(3, "Saved fileset %ld's subset to %s",
1622                    current_tarball_number, filelist_subset_fname);
1623        }
1624        log_to_screen("Tarball #%ld --- %ld matches",
1625                current_tarball_number, matches);
1626    }
1627    mr_free(filelist_name);
1628
1629    if (filelist == NULL || matches > 0) {
1630        if (g_getfattr) {
1631            mr_asprintf(&xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1632                MNT_CDROM "/archives", current_tarball_number);
1633        }
1634        if (g_getfacl) {
1635            mr_asprintf(&acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1636                current_tarball_number);
1637        }
1638        if (strstr(tarball_fname, ".bz2")) {
1639            mr_asprintf(&executable, "-P bzip2 -Z");
1640        } else if (strstr(tarball_fname, ".gz")) {
1641            mr_asprintf(&executable, "-P gzip -Z");
1642        } else if (strstr(tarball_fname, ".lzo")) {
1643            mr_asprintf(&executable, "-P lzop -Z");
1644        }
1645
1646        if (executable == NULL) {
1647            mr_asprintf(&tmp, "which %s > /dev/null 2> /dev/null", executable);
1648            if (run_program_and_log_output(tmp, FALSE)) {
1649                log_to_screen
1650                    (_("(compare_a_tarball) Compression program not found - oh no!"));
1651                mr_free(tmp);
1652                mr_free(executable);
1653                mr_free(acl_fname);
1654                mr_free(xattr_fname);
1655                mr_free(filelist_subset_fname);
1656                paranoid_MR_finish(1);
1657            }
1658            mr_free(tmp);
1659        }
1660        if (use_star) {
1661            mr_asprintf(&command,
1662                    "star -x -force-remove -U " STAR_ACL_SZ
1663                    " errctl= file=%s", tarball_fname);
1664            if (strstr(tarball_fname, ".bz2")) {
1665                mr_strcat(command, " -bz");
1666            }
1667        } else {
1668            if (filelist_subset_fname != NULL) {
1669                mr_asprintf(&command,
1670                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1671                        mr_conf->external_tape_blocksize,
1672                        BUFSIZE, executable, filelist_subset_fname,
1673                        tarball_fname);
1674            } else {
1675                mr_asprintf(&command,
1676                        "afio -i -b %ld -c %ld -M 8m %s %s",
1677                        mr_conf->external_tape_blocksize,
1678                        BUFSIZE, executable, tarball_fname);
1679            }
1680        }
1681        mr_free(executable);
1682
1683        mr_asprintf(&temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1684            (int) (random() % 32768));
1685
1686        mr_strcat(command, " 2>> %s >> %s", temp_log, temp_log);
1687        mr_msg(1, "command = '%s'", command);
1688        unlink(temp_log);
1689        res = system(command);
1690        if (res) {
1691            p = strstr(command, "-acl ");
1692            if (p) {
1693                p[0] = p[1] = p[2] = p[3] = ' ';
1694                mr_msg(1, "new command = '%s'", command);
1695                res = system(command);
1696            }
1697        }
1698        mr_free(command);
1699
1700        if (res && length_of_file(temp_log) < 5) {
1701            res = 0;
1702        }
1703
1704        if (g_getfattr) {
1705            mr_msg(1, "Setting fattr list %s", xattr_fname);
1706            if (length_of_file(xattr_fname) > 0) {
1707                res = set_fattr_list(filelist_subset_fname, xattr_fname);
1708                if (res) {
1709                    log_to_screen
1710                        ("Errors occurred while setting extended attributes");
1711                } else {
1712                    mr_msg(1, "I set xattr OK");
1713                }
1714                retval += res;
1715            }
1716        }
1717        if (g_getfacl) {
1718            mr_msg(1, "Setting acl list %s", acl_fname);
1719            if (length_of_file(acl_fname) > 0) {
1720                res = set_acl_list(filelist_subset_fname, acl_fname);
1721                if (res) {
1722                    log_to_screen
1723                        ("Errors occurred while setting access control lists");
1724                } else {
1725                    mr_msg(1, "I set ACL OK");
1726                }
1727                retval += res;
1728            }
1729        }
1730        if (retval) {
1731            mr_asprintf(&command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1732            system(command);
1733            mr_free(command);
1734            mr_msg(2, "Errors occurred while processing fileset #%d",
1735                    current_tarball_number);
1736        } else {
1737            mr_msg(2, "Fileset #%d processed OK", current_tarball_number);
1738        }
1739        unlink(xattr_fname);
1740        mr_free(xattr_fname);
1741        unlink(acl_fname);
1742        mr_free(acl_fname);
1743        unlink(temp_log);
1744        mr_free(temp_log);
1745    }
1746    if (does_file_exist("/PAUSE")) {
1747        popup_and_OK
1748            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
1749    }
1750    unlink(filelist_subset_fname);
1751    mr_free(filelist_subset_fname);
1752    mr_msg(5, "Leaving");
1753    return (retval);
1754}
1755
1756/**************************************************************************
1757 *END_RESTORE_A_TARBALL_FROM_CD                                           *
1758 **************************************************************************/
1759
1760
1761/**
1762 * Restore a tarball from the currently opened stream.
1763 * @param bkpinfo The backup information structure. Fields used:
1764 * - @c bkpinfo->backup_media_type
1765 * - @c bkpinfo->media_device
1766 * - @c bkpinfo->compression_tool
1767 * @param tarball_fname The filename of the afioball to restore.
1768 * @param current_tarball_number The number (starting from 0) of the fileset
1769 * we're restoring now.
1770 * @param filelist The node structure containing the list of files to be
1771 * restored. If no file in the afioball is in this list, afio will still be
1772 * called, but nothing will be written.
1773 * @param size The size (in @b bytes) of the afioball.
1774 * @return 0 for success, nonzero for failure.
1775 */
1776int
1777restore_a_tarball_from_stream(char *tarball_fname,
1778                              long current_tarball_number,
1779                              struct s_node *filelist,
1780                              long long size, char *xattr_fname,
1781                              char *acl_fname)
1782{
1783    int retval = 0;
1784    int res = 0;
1785
1786  /** malloc add ***/
1787    char *command = NULL;
1788    char *afio_fname = NULL;
1789    char *filelist_fname = NULL;
1790    char *filelist_subset_fname = NULL;
1791    char *executable = NULL;
1792    long matches = 0;
1793    bool restore_this_fileset = FALSE;
1794    bool use_star = FALSE;
1795
1796    assert(bkpinfo != NULL);
1797    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1798    /* to do it with a file... */
1799    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1800    mr_msg(2, "Restoring from fileset #%ld (%ld KB) on %s #%d",
1801            current_tarball_number, (long) size >> 10,
1802            bkpinfo->backup_media_string,
1803            g_current_media_number);
1804    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1805
1806  /****************************************************************************
1807   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
1808   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
1809   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
1810   ****************************************************************************/
1811    mr_asprintf(&afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1812            current_tarball_number);
1813    mr_asprintf(&filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1814            current_tarball_number);
1815    mr_asprintf(&filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1816            bkpinfo->tmpdir, current_tarball_number);
1817    res = read_file_from_stream_to_file(afio_fname, size);
1818    if (strstr(tarball_fname, ".star")) {
1819        bkpinfo->use_star = TRUE;
1820    }
1821    if (res) {
1822        mr_msg(1, "Warning - error reading afioball from tape");
1823    }
1824    if (bkpinfo->compression_level != 0) {
1825        if (bkpinfo->use_star) {
1826            mr_asprintf(&executable, " -bz");
1827        } else {
1828            mr_asprintf(&executable, "-P %s -Z", bkpinfo->compression_tool);
1829        }
1830    }
1831
1832    if (!filelist)              // if unconditional restore then restore entire fileset
1833    {
1834        restore_this_fileset = TRUE;
1835    } else                      // If restoring selectively then get TOC from tarball
1836    {
1837        if (strstr(tarball_fname, ".star.")) {
1838            use_star = TRUE;
1839            mr_asprintf(&command, "star -t file=%s %s", afio_fname, executable);
1840        } else {
1841            use_star = FALSE;
1842            mr_asprintf(&command, "afio -t -M 8m -b %ld %s %s", mr_conf->external_tape_blocksize,
1843                    executable, afio_fname);
1844        }
1845        mr_strcat(command, " > %s 2>> %s", filelist_fname, MONDO_LOGFILE);
1846        mr_msg(1, "command = %s", command);
1847        if (system(command)) {
1848            mr_msg(4, "Warning - error occurred while retrieving TOC");
1849        }
1850        mr_free(command);
1851
1852        if ((matches =
1853             save_filelist_entries_in_common(filelist_fname, filelist,
1854                                             filelist_subset_fname,
1855                                             use_star))
1856            <= 0 || length_of_file(filelist_subset_fname) < 2) {
1857            if (length_of_file(filelist_subset_fname) < 2) {
1858                mr_msg(1, "No matches found in fileset %ld",
1859                        current_tarball_number);
1860            }
1861            mr_msg(2, "Skipping fileset %ld", current_tarball_number);
1862            restore_this_fileset = FALSE;
1863        } else {
1864            mr_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1865                    matches, current_tarball_number,
1866                    filelist_subset_fname);
1867            restore_this_fileset = TRUE;
1868        }
1869    }
1870    unlink(filelist_fname);
1871    mr_free(filelist_fname);
1872
1873// Concoct the call to star/afio to restore files
1874    if (strstr(tarball_fname, ".star.")) {
1875        // star
1876        if (filelist) {
1877            mr_asprintf(&command, "star -x file=%s %s list=%s 2>> %s", afio_fname, executable, filelist_subset_fname, MONDO_LOGFILE);
1878        } else {
1879            mr_asprintf(&command, "star -x file=%s %s 2>> %s", afio_fname, executable, MONDO_LOGFILE);
1880        }
1881    } else {
1882        // afio
1883        if (filelist) {
1884            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);
1885        } else {
1886            mr_asprintf(&command, "afio -i -M 8m -b %ld %s %s 2>> %s", mr_conf->external_tape_blocksize, executable, afio_fname, MONDO_LOGFILE);
1887        }
1888    }
1889    mr_free(executable);
1890
1891    // Call if IF there are files to restore (selectively/unconditionally)
1892    if (restore_this_fileset) {
1893        mr_msg(1, "Calling command='%s'", command);
1894        paranoid_system(command);
1895
1896        if (g_getfattr) {
1897            iamhere("Restoring xattr stuff");
1898            res = set_fattr_list(filelist_subset_fname, xattr_fname);
1899            if (res) {
1900                mr_msg(1, "Errors occurred while setting xattr");
1901            } else {
1902                mr_msg(1, "I set xattr OK");
1903            }
1904            retval += res;
1905        }
1906
1907        if (g_getfacl) {
1908            iamhere("Restoring acl stuff");
1909            res = set_acl_list(filelist_subset_fname, acl_fname);
1910            if (res) {
1911                mr_msg(1, "Errors occurred while setting ACL");
1912            } else {
1913                mr_msg(1, "I set ACL OK");
1914            }
1915            retval += res;
1916        }
1917
1918    } else {
1919        mr_msg(1, "NOT CALLING '%s'", command);
1920    }
1921    mr_free(command);
1922
1923    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1924        log_to_screen(_("Paused after set %ld"), current_tarball_number);
1925        popup_and_OK(_("Pausing. Press ENTER to continue."));
1926    }
1927
1928    unlink(filelist_subset_fname);
1929    unlink(afio_fname);
1930
1931    mr_free(filelist_subset_fname);
1932    mr_free(afio_fname);
1933    return (retval);
1934}
1935
1936/**************************************************************************
1937 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
1938 **************************************************************************/
1939
1940
1941/**
1942 * Restore all biggiefiles from all media in this CD backup.
1943 * The CD with the last afioball should be currently mounted.
1944 * @param bkpinfo The backup information structure. @c backup_media_type is the
1945 * only field used in this function.
1946 * @param filelist The node structure containing the list of files to be
1947 * restored. If a prospective biggiefile is not in this list, it will be ignored.
1948 * @return 0 for success, nonzero for failure.
1949 */
1950int
1951restore_all_biggiefiles_from_CD(struct s_node *filelist)
1952{
1953    int retval = 0;
1954    int res = 0;
1955    long noof_biggiefiles = 0L, bigfileno = 0L, total_slices = 0L;
1956    char *tmp = NULL;
1957    char *tmp1 = NULL;
1958    bool just_changed_cds = FALSE, finished = FALSE;
1959    char *xattr_fname = NULL;
1960    char *acl_fname = NULL;
1961    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
1962    char *pathname_of_last_biggie_restored = NULL;
1963    FILE *fbw = NULL;
1964
1965    malloc_string(tmp1);
1966    malloc_string(pathname_of_last_biggie_restored);
1967    assert(bkpinfo != NULL);
1968
1969    mr_asprintf(&biggies_whose_EXATs_we_should_set,
1970            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
1971    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
1972        mr_msg(1, "Warning - cannot openout %s",
1973                biggies_whose_EXATs_we_should_set);
1974    }
1975
1976    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp1);
1977    total_slices = atol(tmp1);
1978    mr_free(tmp1);
1979
1980    mr_asprintf(&tmp, _("Reassembling large files      "));
1981    mvaddstr_and_log_it(g_currentY, 0, tmp);
1982    mr_free(tmp);
1983
1984    if (length_of_file(BIGGIELIST) < 6) {
1985        mr_msg(1, "OK, no biggielist; not restoring biggiefiles");
1986        return (0);
1987    }
1988    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
1989    if (noof_biggiefiles <= 0) {
1990        mr_msg(2,
1991                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
1992        return (0);
1993    }
1994    mr_msg(2, "OK, there are %ld biggiefiles in the archives", noof_biggiefiles);
1995
1996    open_progress_form(_("Reassembling large files"),
1997                       _("I am now reassembling all the large files."),
1998                       _("Please wait. This may take some time."),
1999                       "", total_slices);
2000    for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
2001        mr_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
2002        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
2003            mr_msg(3,
2004                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
2005            mr_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
2006                    bigfileno + 1,
2007                    bkpinfo->backup_media_string,
2008                    g_current_media_number);
2009            mr_msg(3, "Slicename would have been %s",
2010                    slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
2011            // I'm not positive 'just_changed_cds' is even necessary...
2012            if (just_changed_cds) {
2013                just_changed_cds = FALSE;
2014                mr_msg(3,
2015                        "I'll continue to scan this CD for bigfiles to be restored.");
2016            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2017                insist_on_this_cd_number(++g_current_media_number);
2018                log_to_screen(_("Restoring from %s #%d"),
2019                        media_descriptor_string(bkpinfo->backup_media_type),
2020                        g_current_media_number);
2021                just_changed_cds = TRUE;
2022            } else {
2023                /* That big file doesn't exist, but the followings may */
2024                /* So we need to continue looping */
2025                mr_msg(2, "There was no bigfile #%ld. That's OK.",
2026                    bigfileno + 1);
2027                mr_msg(2, "I'm going to stop restoring bigfiles now.");
2028                retval++;
2029                bigfileno++;
2030            }
2031        } else {
2032            just_changed_cds = FALSE;
2033            mr_asprintf(&tmp, _("Restoring big file %ld"), bigfileno + 1);
2034            update_progress_form(tmp);
2035            mr_free(tmp);
2036
2037            res =
2038                restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
2039            iamhere(pathname_of_last_biggie_restored);
2040            if (fbw && pathname_of_last_biggie_restored[0]) {
2041                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2042            }
2043            retval += res;
2044            bigfileno++;
2045        }
2046    }
2047
2048    if (fbw) {
2049        fclose(fbw);
2050        if (g_getfattr) {
2051            mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2052            if (length_of_file(xattr_fname) > 0) {
2053                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2054            }
2055        }
2056        if (g_getfacl) {
2057            mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2058            if (length_of_file(acl_fname) > 0) {
2059                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2060            }
2061        }
2062        mr_free(acl_fname);
2063        mr_free(xattr_fname);
2064    }
2065    mr_free(biggies_whose_EXATs_we_should_set);
2066
2067    if (does_file_exist("/PAUSE")) {
2068        popup_and_OK
2069            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2070    }
2071    close_progress_form();
2072    if (retval) {
2073        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2074    } else {
2075        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2076    }
2077    mr_free(pathname_of_last_biggie_restored);
2078    return (retval);
2079}
2080
2081/**************************************************************************
2082 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2083 **************************************************************************/
2084
2085
2086/**
2087 * Restore all afioballs from all CDs in the backup.
2088 * The first CD should be inserted (if not, it will be asked for).
2089 * @param bkpinfo The backup information structure. @c backup_media_type is the
2090 * only field used in @e this function.
2091 * @param filelist The node structure containing the list of files to be
2092 * restored. If no file in some particular afioball is in this list, afio will
2093 * still be called for that fileset, but nothing will be written.
2094 * @return 0 for success, or the number of filesets that failed.
2095 */
2096int
2097restore_all_tarballs_from_CD(struct s_node *filelist)
2098{
2099    int retval = 0;
2100    int res = 0;
2101    int attempts = 0;
2102    long current_tarball_number = 0;
2103    long max_val = 0L;
2104  /**malloc ***/
2105    char *tmp = NULL;
2106    char *tmp1 = NULL;
2107    char *tarball_fname = NULL;
2108    char *progress_str = NULL;
2109    char *comment = NULL;
2110
2111    malloc_string(tmp1);
2112    malloc_string(tarball_fname);
2113    malloc_string(progress_str);
2114    malloc_string(comment);
2115
2116    assert(bkpinfo != NULL);
2117
2118    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2119    mr_msg(2,
2120            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2121    if (g_current_media_number != 1) {
2122        mr_msg(3, "OK, that's jacked up.");
2123        g_current_media_number = 1;
2124    }
2125    insist_on_this_cd_number(g_current_media_number);
2126    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp1);
2127    max_val = atol(tmp1) + 1;
2128    mr_free(tmp1);
2129
2130    mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2131            bkpinfo->backup_media_string,
2132            g_current_media_number);
2133    log_to_screen(progress_str);
2134    open_progress_form(_("Restoring from archives"),
2135                       _("Restoring data from the archives."),
2136                       _("Please wait. This may take some time."),
2137                       progress_str, max_val);
2138    for (;;) {
2139        insist_on_this_cd_number(g_current_media_number);
2140        update_progress_form(progress_str);
2141        mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2142                current_tarball_number);
2143        if (!does_file_exist(tarball_fname)) {
2144            mr_free(tarball_fname);
2145            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2146                    current_tarball_number);
2147        }
2148        if (!does_file_exist(tarball_fname)) {
2149            mr_free(tarball_fname);
2150            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2151                current_tarball_number);
2152        }
2153        if (!does_file_exist(tarball_fname)) {
2154            mr_free(tarball_fname);
2155            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2156                    current_tarball_number);
2157        }
2158        if (!does_file_exist(tarball_fname)) {
2159            mr_free(tarball_fname);
2160            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2161                    current_tarball_number);
2162        }
2163        if (!does_file_exist(tarball_fname)) {
2164            mr_free(tarball_fname);
2165            mr_asprintf(&tarball_fname, MNT_CDROM "/archives/%ld.star.",
2166                    current_tarball_number);
2167        }
2168        if (!does_file_exist(tarball_fname)) {
2169            mr_free(tarball_fname);
2170            if (current_tarball_number == 0) {
2171                log_to_screen
2172                    (_("No tarballs. Strange. Maybe you only backed up freakin' big files?"));
2173                mr_free(progress_str);
2174                return (0);
2175            }
2176            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2177                || system("find " MNT_CDROM
2178                          "/archives/slice* > /dev/null 2> /dev/null") ==
2179                0) {
2180                mr_free(tarball_fname);
2181                mr_free(progress_str);
2182                break;
2183            }
2184            g_current_media_number++;
2185            mr_free(progress_str);
2186
2187            mr_asprintf(&progress_str, _("Restoring from %s #%d"),
2188                    bkpinfo->backup_media_string,
2189                    g_current_media_number);
2190            log_to_screen(progress_str);
2191        } else {
2192            mr_free(progress_str);
2193            mr_asprintf(&progress_str,
2194                    _("Restoring from fileset #%ld on %s #%d"),
2195                    current_tarball_number,
2196                    bkpinfo->backup_media_string,
2197                    g_current_media_number);
2198            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2199                 attempts++) {
2200                res =
2201                    restore_a_tarball_from_CD(tarball_fname,
2202                                              current_tarball_number,
2203                                              filelist, bkpinfo);
2204            }
2205            mr_asprintf(&tmp, _("%s #%d, fileset #%ld - restore "),
2206                    media_descriptor_string(bkpinfo->backup_media_type),
2207                    g_current_media_number, current_tarball_number);
2208            if (res) {
2209                mr_strcat(tmp, _("reported errors"));
2210            } else {
2211                mr_strcat(tmp, _("succeeded"));
2212            }
2213            if (attempts > 1) {
2214                mr_strcat(tmp, _(" (%d attempts) - review logs"), attempts);
2215            }
2216            if (attempts > 1) {
2217                log_to_screen(tmp);
2218            }
2219            mr_free(tmp);
2220
2221            retval += res;
2222            current_tarball_number++;
2223            g_current_progress++;
2224        }
2225        mr_free(tarball_fname);
2226    }
2227    mr_free(progress_str);
2228    close_progress_form();
2229
2230    if (retval) {
2231        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2232    } else {
2233        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2234    }
2235    return (retval);
2236}
2237
2238/**************************************************************************
2239 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2240 **************************************************************************/
2241
2242
2243/**
2244 * Restore all biggiefiles from the currently opened stream.
2245 * @param bkpinfo The backup information structure. Passed to other functions.
2246 * @param filelist The node structure containing the list of files to be
2247 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2248 * @return 0 for success, or the number of biggiefiles that failed.
2249 */
2250int
2251restore_all_biggiefiles_from_stream(struct s_node *filelist)
2252{
2253    long noof_biggiefiles = 0L;
2254    long current_bigfile_number = 0L;
2255    long total_slices = 0L;
2256
2257    int retval = 0;
2258    int res = 0;
2259    int ctrl_chr = 0;
2260
2261  /** malloc add ****/
2262    char *tmp = NULL;
2263    char *biggie_fname = NULL;
2264    char *biggie_cksum = NULL;
2265    char *xattr_fname = NULL;
2266    char *acl_fname = NULL;
2267    char *pathname_of_last_biggie_restored = NULL;
2268    char *biggies_whose_EXATs_we_should_set = NULL; // EXtended ATtributes
2269    long long biggie_size = (long long)0;
2270    FILE *fbw;
2271
2272    assert(bkpinfo != NULL);
2273
2274    malloc_string(tmp);
2275    malloc_string(biggie_fname);
2276    malloc_string(biggie_cksum);
2277    malloc_string(pathname_of_last_biggie_restored);
2278    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2279    total_slices = atol(tmp);
2280    mr_free(tmp);
2281
2282    mr_asprintf(&tmp, "Reassembling large files      ");
2283    if (g_getfattr) {
2284        mr_asprintf(&xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2285    }
2286    if (g_getfacl) {
2287        mr_asprintf(&acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2288    }
2289    mvaddstr_and_log_it(g_currentY, 0, tmp);
2290    mr_free(tmp);
2291
2292    mr_asprintf(&biggies_whose_EXATs_we_should_set,
2293            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2294    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2295        mr_msg(1, "Warning - cannot openout %s",
2296                biggies_whose_EXATs_we_should_set);
2297    }
2298    // get xattr and acl files if they're there
2299    res =
2300        read_header_block_from_stream(&biggie_size, biggie_fname,
2301                                      &ctrl_chr);
2302    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2303        res =
2304            read_EXAT_files_from_tape(&biggie_size, biggie_fname,
2305                                      &ctrl_chr, xattr_fname, acl_fname);
2306    }
2307
2308    noof_biggiefiles = atol(biggie_fname);
2309    mr_msg(2, "OK, there are %ld biggiefiles in the archives",
2310            noof_biggiefiles);
2311    open_progress_form(_("Reassembling large files"),
2312                       _("I am now reassembling all the large files."),
2313                       _("Please wait. This may take some time."),
2314                       "", total_slices);
2315
2316    for (res =
2317         read_header_block_from_stream(&biggie_size, biggie_fname,
2318                                       &ctrl_chr);
2319         ctrl_chr != BLK_STOP_BIGGIEFILES;
2320         res =
2321         read_header_block_from_stream(&biggie_size, biggie_fname,
2322                                       &ctrl_chr)) {
2323        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2324            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2325            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2326        }
2327        /* BERLIOS: useless
2328        p = strrchr(biggie_fname, '/');
2329        if (!p) {
2330            p = biggie_fname;
2331        } else {
2332            p++;
2333        }
2334        */
2335        mr_asprintf(&tmp, _("Restoring big file %ld (%lld K)"),
2336                current_bigfile_number + 1, biggie_size / 1024);
2337        update_progress_form(tmp);
2338        mr_free(tmp);
2339
2340        res = restore_a_biggiefile_from_stream(biggie_fname,
2341                                               current_bigfile_number,
2342                                               biggie_cksum,
2343                                               biggie_size,
2344                                               filelist, ctrl_chr,
2345                                               pathname_of_last_biggie_restored);
2346        mr_msg(1, "I believe I have restored %s",
2347                pathname_of_last_biggie_restored);
2348        if (fbw && pathname_of_last_biggie_restored[0]) {
2349            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2350        }
2351        mr_free(pathname_of_last_biggie_restored);
2352
2353        retval += res;
2354        current_bigfile_number++;
2355
2356    }
2357    if (current_bigfile_number != noof_biggiefiles
2358        && noof_biggiefiles != 0) {
2359        mr_msg(1, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2360                current_bigfile_number, noof_biggiefiles);
2361    } else {
2362        mr_msg(1, "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2363                noof_biggiefiles, current_bigfile_number);
2364    }
2365
2366    if (fbw) {
2367        fclose(fbw);
2368        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2369            iamhere("Setting biggie-EXATs");
2370            if (g_getfattr) {
2371                if (length_of_file(xattr_fname) > 0) {
2372                    mr_msg(1, "set_fattr_List(%s,%s)",
2373                        biggies_whose_EXATs_we_should_set, xattr_fname);
2374                    set_fattr_list(biggies_whose_EXATs_we_should_set,
2375                               xattr_fname);
2376                }
2377            }
2378            if (g_getfacl) {
2379                if (length_of_file(acl_fname) > 0) {
2380                    mr_msg(1, "set_acl_list(%s,%s)",
2381                            biggies_whose_EXATs_we_should_set, acl_fname);
2382                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2383                }
2384            }
2385        } else {
2386            iamhere
2387                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2388        }
2389    }
2390    mr_free(xattr_fname);
2391    mr_free(acl_fname);
2392    mr_free(biggies_whose_EXATs_we_should_set);
2393
2394    if (does_file_exist("/PAUSE")) {
2395        popup_and_OK
2396            (_("Press ENTER to go on. Delete /PAUSE to stop these pauses."));
2397    }
2398
2399    close_progress_form();
2400    if (retval) {
2401        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2402    } else {
2403        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2404    }
2405    mr_free(biggie_fname);
2406    mr_free(biggie_cksum);
2407    return (retval);
2408}
2409
2410/**************************************************************************
2411 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2412 **************************************************************************/
2413
2414
2415/**
2416 * Restore all afioballs from the currently opened tape stream.
2417 * @param bkpinfo The backup information structure. Fields used:
2418 * - @c bkpinfo->backup_media_type
2419 * - @c bkpinfo->restore_path
2420 * @param filelist The node structure containing the list of files to be
2421 * restored. If no file in an afioball is in this list, afio will still be
2422 * called for that fileset, but nothing will be written.
2423 * @return 0 for success, or the number of filesets that failed.
2424 */
2425int
2426restore_all_tarballs_from_stream(struct s_node *filelist)
2427{
2428    int retval = 0;
2429    int res = 0;
2430    long current_afioball_number = 0;
2431    int ctrl_chr = 0;
2432    long max_val = 0L /*, total_noof_files */ ;
2433
2434  /** malloc **/
2435    char *tmp = NULL;
2436    char *progress_str = NULL;
2437    char *tmp_fname = NULL;
2438    char *xattr_fname = NULL;
2439    char *acl_fname = NULL;
2440
2441    long long tmp_size = 0L;
2442
2443    malloc_string(tmp_fname);
2444    malloc_string(tmp);
2445    assert(bkpinfo != NULL);
2446    mvaddstr_and_log_it(g_currentY, 0, _("Restoring from archives"));
2447    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2448    max_val = atol(tmp) + 1;
2449    mr_free(tmp);
2450
2451    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2452
2453    run_program_and_log_output("pwd", 5);
2454
2455    mr_asprintf(&progress_str, _("Restoring from media #%d"),
2456            g_current_media_number);
2457    log_to_screen(progress_str);
2458    open_progress_form(_("Restoring from archives"),
2459                       _("Restoring data from the archives."),
2460                       _("Please wait. This may take some time."),
2461                       progress_str, max_val);
2462
2463    mr_msg(3, "hey");
2464
2465    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2466    if (res) {
2467        mr_msg(2, "Warning - error reading afioball from tape");
2468    }
2469    retval += res;
2470    if (ctrl_chr != BLK_START_AFIOBALLS) {
2471        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2472    }
2473    mr_msg(2, "ho");
2474    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2475    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2476        update_progress_form(progress_str);
2477        if (g_getfattr) {
2478            mr_asprintf(&xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2479                current_afioball_number);
2480            unlink(xattr_fname);
2481        }
2482        if (g_getfacl) {
2483            mr_asprintf(&acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2484                current_afioball_number);
2485            unlink(acl_fname);
2486        }
2487        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2488            iamhere("Reading EXAT files from tape");
2489            res =
2490                read_EXAT_files_from_tape(&tmp_size, tmp_fname,
2491                                          &ctrl_chr, xattr_fname,
2492                                          acl_fname);
2493        }
2494        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2495            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2496        }
2497        /* BERLIOS: useless ?
2498        mr_asprintf(&tmp,
2499                _("Restoring from fileset #%ld (name=%s, size=%ld K)"),
2500                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2501                */
2502        res =
2503            restore_a_tarball_from_stream(tmp_fname,
2504                                          current_afioball_number,
2505                                          filelist, tmp_size, xattr_fname,
2506                                          acl_fname);
2507        retval += res;
2508        if (res) {
2509            log_to_screen("Fileset %ld - errors occurred",
2510                    current_afioball_number);
2511        }
2512        res =
2513            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2514        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2515            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2516        }
2517
2518        current_afioball_number++;
2519        g_current_progress++;
2520
2521        mr_free(progress_str);
2522        mr_asprintf(&progress_str, _("Restoring from fileset #%ld on %s #%d"),
2523                current_afioball_number,
2524                bkpinfo->backup_media_string,
2525                g_current_media_number);
2526        res =
2527            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2528        if (g_getfattr) {
2529            unlink(xattr_fname);
2530        }
2531        if (g_getfacl) {
2532            unlink(acl_fname);
2533        }
2534        mr_free(xattr_fname);
2535        mr_free(acl_fname);
2536    }                           // next
2537    mr_free(progress_str);
2538    mr_free(tmp_fname);
2539
2540    mr_msg(1, "All done with afioballs");
2541    close_progress_form();
2542    if (retval) {
2543        mvaddstr_and_log_it(g_currentY++, 74, _("Errors."));
2544    } else {
2545        mvaddstr_and_log_it(g_currentY++, 74, _("Done."));
2546    }
2547    return (retval);
2548}
2549
2550/**************************************************************************
2551 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2552 **************************************************************************/
2553
2554/* @} - end of LLrestoreGroup */
2555
2556
2557/**
2558 * Restore all files in @p filelist.
2559 * @param bkpinfo The backup information structure. Most fields are used.
2560 * @param filelist The node structure containing the list of files to be
2561 * restored.
2562 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2563 * @ingroup restoreGroup
2564 */
2565int restore_everything(struct s_node *filelist)
2566{
2567    int resA;
2568    int resB;
2569
2570  /** mallco ***/
2571    char *cwd = NULL;
2572    char *newpath = NULL;
2573    char *tmp = NULL;
2574    assert(bkpinfo != NULL);
2575
2576    malloc_string(cwd);
2577    malloc_string(newpath);
2578    mr_msg(2, "restore_everything() --- starting");
2579    g_current_media_number = 1;
2580    /* BERLIOS: should test return value, or better change the function */
2581    getcwd(cwd, MAX_STR_LEN - 1);
2582    mr_asprintf(&tmp, "mkdir -p %s", bkpinfo->restore_path);
2583    run_program_and_log_output(tmp, FALSE);
2584    mr_free(tmp);
2585
2586    mr_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2587    chdir(bkpinfo->restore_path);
2588    /* BERLIOS: should test return value, or better change the function */
2589    getcwd(newpath, MAX_STR_LEN - 1);
2590    mr_msg(1, "path is now %s", newpath);
2591    mr_msg(1, "restoring everything");
2592    if (!find_home_of_exe("petris") && !g_text_mode) {
2593        newtDrawRootText(0, g_noof_rows - 2,
2594                         _("Press ALT-<left cursor> twice to play Petris :-) "));
2595        newtRefresh();
2596    }
2597    mvaddstr_and_log_it(g_currentY, 0, _("Preparing to read your archives"));
2598    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2599        mount_media();
2600        mvaddstr_and_log_it(g_currentY++, 0,
2601                            _("Restoring OS and data from streaming media"));
2602        if (bkpinfo->backup_media_type == cdstream) {
2603            openin_cdstream();
2604        } else {
2605            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
2606            openin_tape();
2607        }
2608        resA = restore_all_tarballs_from_stream(filelist);
2609        resB = restore_all_biggiefiles_from_stream(filelist);
2610        if (bkpinfo->backup_media_type == cdstream) {
2611            closein_cdstream();
2612        } else {
2613            closein_tape();
2614        }
2615    } else {
2616        mvaddstr_and_log_it(g_currentY++, 0,
2617                            _("Restoring OS and data from CD/USB   "));
2618        mount_media();
2619        resA = restore_all_tarballs_from_CD(filelist);
2620        resB = restore_all_biggiefiles_from_CD(filelist);
2621    }
2622    chdir(cwd);
2623    if (resA + resB) {
2624        log_to_screen(_("Errors occurred while data was being restored."));
2625    }
2626    if (length_of_file("/etc/raidtab") > 0) {
2627        mr_msg(2, "Copying local raidtab to restored filesystem");
2628        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2629                                   "/etc/raidtab", FALSE);
2630    }
2631    kill_petris();
2632    mr_msg(2, "restore_everything() --- leaving");
2633    mr_free(cwd);
2634    mr_free(newpath);
2635    return (resA + resB);
2636}
2637
2638/**************************************************************************
2639 *END_RESTORE_EVERYTHING                                                  *
2640 **************************************************************************/
2641
2642
2643/**
2644 * @brief Haha. You wish! (This function is not implemented :-)
2645 */
2646int
2647restore_live_from_monitas_server(char *monitas_device,
2648                                 char *restore_this_directory,
2649                                 char *restore_here)
2650     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2651{
2652    FILE *fout;
2653    int retval = 0;
2654    int i;
2655    int j;
2656    struct mountlist_itself the_mountlist;
2657    static struct raidlist_itself the_raidlist;
2658  /** malloc **/
2659    char tmp[MAX_STR_LEN + 1];
2660    char command[MAX_STR_LEN + 1];
2661    char datablock[256 * 1024];
2662    char datadisks_fname[MAX_STR_LEN + 1];
2663    long k;
2664    long length;
2665    long long llt;
2666    struct s_node *filelist = NULL;
2667    assert(bkpinfo != NULL);
2668    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2669    assert(restore_this_directory != NULL);
2670    assert(restore_here != NULL);
2671
2672    sprintf(tmp, "restore_here = '%s'", restore_here);
2673
2674    mr_msg(2, tmp);
2675
2676    mr_msg(2, "restore_live_from_monitas_server() - starting");
2677    unlink("/tmp/mountlist.txt");
2678    unlink("/tmp/filelist.full");
2679    unlink("/tmp/biggielist.txt");
2680    if (restore_here[0] == '\0') {
2681        strcpy(bkpinfo->restore_path, MNT_RESTORING);
2682    } else {
2683        strcpy(bkpinfo->restore_path, restore_here);
2684    }
2685    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2686    sprintf(tmp, "FYI - data will be restored to %s",
2687            bkpinfo->restore_path);
2688    mr_msg(3, tmp);
2689    mr_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2690    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2691            (int) (random() % 32768));
2692    chdir(bkpinfo->tmpdir);
2693
2694    sprintf(command, "cat %s", monitas_device);
2695    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
2696    if (!(fout = fopen(datadisks_fname, "w"))) {
2697        log_OS_error(datadisks_fname);
2698        return (1);
2699    }
2700    for (i = 0; i < 32; i++) {
2701        for (j = 0; j < 4; j++) {
2702            for (length = k = 0; length < 256 * 1024; length += k) {
2703                k = fread(datablock + length, 1, 256 * 1024 - length,
2704                          g_tape_stream);
2705            }
2706            fwrite(datablock, 1, length, fout);
2707            g_tape_posK += length;
2708        }
2709    }
2710    paranoid_fclose(fout);
2711    sprintf(command,
2712            "tar -zxvf %s ./tmp/mondo-restore.cfg ./tmp/mountlist.txt ./tmp/filelist.full ./tmp/biggielist.txt",
2713            datadisks_fname);
2714    run_program_and_log_output(command, 4);
2715    read_header_block_from_stream(&llt, tmp, &i);
2716    read_header_block_from_stream(&llt, tmp, &i);
2717
2718    unlink(datadisks_fname);
2719    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
2720    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
2721
2722
2723    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2724    iamhere("FIXME");
2725    fatal_error("This will fail");
2726    sprintf(command,
2727            "grep -E '^%s.*$' %s > %s",
2728            restore_this_directory, g_filelist_full, g_filelist_full);
2729    if (system(command)) {
2730        retval++;
2731        log_to_screen
2732            ("Error(s) occurred while processing filelist and wildcard");
2733    }
2734    iamhere("FIXME");
2735    fatal_error("This will fail");
2736    sprintf(command,
2737            "grep -E '^%s.*$' %s > %s",
2738            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2739    if (system(command)) {
2740        mr_msg(1,
2741                "Error(s) occurred while processing biggielist and wildcard");
2742    }
2743    sprintf(command, "touch %s", g_biggielist_txt);
2744    run_program_and_log_output(command, FALSE);
2745//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2746    retval += restore_everything(filelist);
2747    free_filelist(filelist);
2748    mr_msg(2, "--------End of restore_live_from_monitas_server--------");
2749    return (retval);
2750}
2751
2752/**************************************************************************
2753 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
2754 **************************************************************************/
2755
2756
2757
2758
2759extern void wait_until_software_raids_are_prepped(int);
2760
2761char which_restore_mode(void);
2762
2763
2764/**
2765 * Log a "don't panic" message to the logfile.
2766 */
2767void welcome_to_mondorestore(void)
2768{
2769    mr_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2770    mr_msg(0,
2771            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2772    mr_msg(0,
2773            "don't break out in a cold sweat just because you see a few  ");
2774    mr_msg(0,
2775            "error messages in the log. Read them; analyze them; see if  ");
2776    mr_msg(0,
2777            "they are significant; above all, verify your backups! Please");
2778    mr_msg(0,
2779            "attach a compressed copy of this log to any e-mail you send ");
2780    mr_msg(0,
2781            "to the Mondo mailing list when you are seeking technical    ");
2782    mr_msg(0,
2783            "support. Without it, we can't help you.            - DevTeam");
2784    mr_msg(0,
2785            "------------------------------------------------------------");
2786    mr_msg(0,
2787            "BTW, despite (or perhaps because of) the wealth of messages,");
2788    mr_msg(0,
2789            "some users are inclined to stop reading this log.  If Mondo ");
2790    mr_msg(0,
2791            "stopped for some reason, chances are it's detailed here.    ");
2792    mr_msg(0,
2793            "More than likely there's a message near the end of this     ");
2794    mr_msg(0,
2795            "log that will tell you what is wrong.  Please read it!      ");
2796    mr_msg(0,
2797            "------------------------------------------------------------");
2798}
2799
2800
2801/**
2802 * Restore the user's data.
2803 * What did you think it did, anyway? :-)
2804 */
2805int main(int argc, char *argv[])
2806{
2807    FILE *fin = NULL;
2808    FILE *fout = NULL;
2809    int retval = 0;
2810    int res = 0;
2811    char *tmp = NULL;
2812
2813    struct mountlist_itself *mountlist = NULL;
2814    struct raidlist_itself *raidlist = NULL;
2815    struct s_node *filelist = NULL;
2816    char *a = NULL, *b = NULL;
2817    bool run_postnuke = FALSE;
2818
2819#ifdef ENABLE_NLS
2820    setlocale(LC_ALL, "");
2821    (void) textdomain("mondo");
2822#endif
2823
2824    /* Reference the right cleanup function for mr_exit */
2825    mr_cleanup = &mr_rs_cleanup;
2826
2827    if (getuid() != 0) {
2828        fprintf(stderr, _("Please run as root.\n"));
2829        mr_exit(127, NULL);
2830    }
2831    /* Conf file management */
2832    mr_conf = mr_malloc(sizeof(struct mr_rs_conf));
2833    mr_rs_reset_conf(mr_conf);
2834    bkpinfo = mr_malloc(sizeof(struct s_bkpinfo));
2835    reset_bkpinfo();
2836
2837    mr_conf->log_level = DEFAULT_MR_LOGLEVEL;
2838
2839/* Configure global variables */
2840#ifdef __FreeBSD__
2841    if (strstr
2842        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2843         "textonly"))
2844#else
2845    if (strstr
2846        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2847         "textonly"))
2848#endif
2849    {
2850        g_text_mode = TRUE;
2851        mr_msg(1, "TEXTONLY MODE");
2852    } else {
2853        g_text_mode = FALSE;
2854    }                           // newt :-)
2855    mountlist = mr_malloc(sizeof(struct mountlist_itself));
2856    raidlist = mr_malloc(sizeof(struct raidlist_itself));
2857
2858    malloc_libmondo_global_strings();
2859
2860    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2861    make_hole_for_dir(g_tmpfs_mountpt);
2862    g_current_media_number = 1; // precaution
2863
2864    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2865
2866    malloc_string(a);
2867    malloc_string(b);
2868    setup_MR_global_filenames();    // malloc() and set globals, using bkpinfo->tmpdir etc.
2869    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2870    strcpy(bkpinfo->backup_media_string,"");
2871    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2872    if (am_I_in_disaster_recovery_mode()) {
2873        run_program_and_log_output("mount / -o remount,rw", 2);
2874    }                           // for b0rken distros
2875    g_main_pid = getpid();
2876    srandom((int) (time(NULL)));
2877    register_pid(getpid(), "mondo");
2878    set_signals(TRUE);
2879    g_kernel_version = get_kernel_version();
2880
2881    mr_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2882    if (strlen(g_mountlist_fname) < 3) {
2883        fatal_error
2884            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2885    }
2886    mkdir(MNT_CDROM, 0x770);
2887    make_hole_for_dir(MONDO_CACHE);
2888
2889    /* Backup original mountlist.txt */
2890    mr_asprintf(&tmp, "%s.orig", g_mountlist_fname);
2891    if (!does_file_exist(g_mountlist_fname)) {
2892        mr_msg(2,
2893                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2894                __LINE__, g_mountlist_fname);
2895    } else if (!does_file_exist(tmp)) {
2896        mr_free(tmp);
2897        mr_asprintf(&tmp, "cp -f %s %s.orig", g_mountlist_fname,
2898                g_mountlist_fname);
2899        run_program_and_log_output(tmp, FALSE);
2900    }
2901    mr_free(tmp);
2902
2903    /* Init directories */
2904    make_hole_for_dir("/var/log");
2905    make_hole_for_dir("/tmp/tmpfs");    /* just in case... */
2906    run_program_and_log_output("umount " MNT_CDROM, FALSE);
2907
2908    run_program_and_log_output("rm -Rf /tmp/tmpfs/mondo.tmp.*", FALSE);
2909
2910    /* Init GUI */
2911    malloc_libmondo_global_strings();
2912    setup_newt_stuff();         /* call newtInit and setup screen log */
2913    welcome_to_mondorestore();
2914    if (bkpinfo->disaster_recovery) {
2915        mr_msg(1, "I am in disaster recovery mode");
2916    } else {
2917        mr_msg(1, "I am in normal, live mode");
2918    }
2919
2920    iamhere("what time is it");
2921
2922    /* Process command-line parameters */
2923    if (argc == 2 && strcmp(argv[1], "--edit-mountlist") == 0) {
2924#ifdef __FreeBSD__
2925        system("mv -f /tmp/raidconf.txt /etc/raidtab");
2926        if (!does_file_exist("/etc/raidtab"))
2927            system("vinum printconfig > /etc/raidtab");
2928#endif
2929        load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
2930        if (!does_file_exist(g_mountlist_fname)) {
2931            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
2932        }
2933        res = let_user_edit_the_mountlist(mountlist, raidlist);
2934#ifdef __FreeBSD__
2935        system("mv -f /etc/raidtab /tmp/raidconf.txt");
2936#endif
2937        paranoid_MR_finish(res);
2938    }
2939
2940    mr_conf->log_level = DEFAULT_MR_LOGLEVEL;
2941    if (argc == 3 && strcmp(argv[1], "--echo-to-screen") == 0) {
2942        fout = fopen("/tmp/out.txt", "w");
2943        fput_string_one_char_at_a_time(stderr, argv[2]);
2944        finish(0);
2945    }
2946
2947    if (argc == 3 && strcmp(argv[1], "--gendf") == 0) {
2948        make_grub_install_scriptlet(argv[2]);
2949        finish(0);
2950    }
2951
2952    if (argc == 5 && strcmp(argv[1], "--common") == 0) {
2953        mr_conf->log_level = 6;
2954        filelist = load_filelist(argv[2]);
2955        if (!filelist) {
2956            fatal_error("Failed to load filelist");
2957        }
2958        toggle_node_selection(filelist, FALSE);
2959        toggle_all_root_dirs_on(filelist);
2960        // BERLIOS: /usr/lib ???
2961        toggle_path_selection(filelist, "/usr/share", TRUE);
2962        save_filelist(filelist, "/tmp/out.txt");
2963        mr_asprintf(&a, argv[3]);
2964        mr_asprintf(&b, argv[4]);
2965
2966        res = save_filelist_entries_in_common(a, filelist, b, FALSE);
2967        free_filelist(filelist);
2968        mr_free(a);
2969        mr_free(b);
2970        printf("res = %d", res);
2971        finish(0);
2972    }
2973
2974    if (argc == 3 && strcmp(argv[1], "--popuplist") == 0) {
2975        popup_changelist_from_file(argv[2]);
2976        paranoid_MR_finish(0);
2977    }
2978
2979    if (argc == 5 && strcmp(argv[1], "--copy") == 0) {
2980        mr_msg(1, "SCORE");
2981        mr_conf->log_level = 10;
2982        if (strstr(argv[2], "save")) {
2983            mr_msg(1, "Saving from %s to %s", argv[3], argv[4]);
2984            fin = fopen(argv[3], "r");
2985            fout = fopen(argv[4], "w");
2986            copy_from_src_to_dest(fin, fout, 'w');
2987            fclose(fin);
2988            fin = fopen(argv[3], "r");
2989            copy_from_src_to_dest(fin, fout, 'w');
2990            fclose(fout);
2991            fclose(fin);
2992        } else if (strstr(argv[2], "restore")) {
2993            fout = fopen(argv[3], "w");
2994            fin = fopen(argv[4], "r");
2995            copy_from_src_to_dest(fout, fin, 'r');
2996            fclose(fin);
2997            fin = fopen(argv[4], "r");
2998            copy_from_src_to_dest(fout, fin, 'r');
2999            fclose(fout);
3000            fclose(fin);
3001        } else {
3002            fatal_error("Unknown additional param");
3003        }
3004        finish(0);
3005    }
3006
3007    if (argc == 2 && strcmp(argv[1], "--mdstat") == 0) {
3008        wait_until_software_raids_are_prepped(100);
3009        finish(0);
3010    }
3011
3012    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
3013        finish(create_raidtab_from_mdstat(argv[2]));
3014    }
3015
3016    if (argc == 3 && strcmp(argv[1], "-p") == 0) {
3017        mr_allocstr(bkpinfo->prefix,argv[2]);
3018        mr_msg(1,"Prefix forced to %s",bkpinfo->prefix);
3019    }
3020
3021    if (argc == 3 && strcmp(argv[1], "-K") == 0) {
3022        g_loglevel = atoi(argv[2]);
3023        log_msg(1,"Loglevel forced to %s",g_loglevel);
3024    }
3025
3026    if (argc == 2 && strcmp(argv[1], "--live-grub") == 0) {
3027        retval = run_grub(FALSE, "/dev/hda");
3028        if (retval) {
3029            log_to_screen(_("Failed to write Master Boot Record"));
3030        }
3031        paranoid_MR_finish(0);
3032    }
3033    if (argc == 3 && strcmp(argv[1], "--paa") == 0) {
3034        g_current_media_number = atoi(argv[2]);
3035        pause_and_ask_for_cdr(5);
3036        paranoid_MR_finish(0);
3037    } else if (!bkpinfo->disaster_recovery) {   // live!
3038        if (argc != 1) {
3039            popup_and_OK
3040                (_("Live mode doesn't support command-line parameters yet."));
3041            paranoid_MR_finish(1);
3042        }
3043        mr_msg(1, "I am in normal, live mode.");
3044        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s", g_mountlist_fname);
3045        mount_boot_if_necessary();  /* for Gentoo users */
3046        mr_msg(2, "Still here.");
3047        if (argc > 1 && strcmp(argv[argc - 1], "--live-from-cd") == 0) {
3048            g_restoring_live_from_cd = TRUE;
3049        }
3050        if (bkpinfo->backup_media_type == nfs) {
3051            g_restoring_live_from_nfs = TRUE;
3052        }
3053        if (argc == 5 && strcmp(argv[1], "--monitas-live") == 0) {
3054            retval =
3055                restore_live_from_monitas_server(argv[2],
3056                                                 argv[3], argv[4]);
3057        } else {
3058            mr_msg(2, "Calling restore_to_live_filesystem()");
3059            retval = restore_to_live_filesystem();
3060        }
3061        mr_msg(2, "Still here. Yay.");
3062        if (strlen(bkpinfo->tmpdir) > 0) {
3063            mr_asprintf(&tmp, "rm -Rf %s/*", bkpinfo->tmpdir);
3064            run_program_and_log_output(tmp, FALSE);
3065            mr_free(tmp);
3066        }
3067        unmount_boot_if_necessary();    /* for Gentoo users */
3068        paranoid_MR_finish(retval);
3069    } else {
3070        /* Disaster recovery mode (must be) */
3071        mr_msg(1, "I must be in disaster recovery mode.");
3072        mr_msg(2, "FYI, MOUNTLIST_FNAME = %s ", g_mountlist_fname);
3073        if (argc == 3 && strcmp(argv[1], "--monitas-memorex") == 0) {
3074            log_to_screen(_("Uh, that hasn't been implemented yet."));
3075            paranoid_MR_finish(1);
3076        }
3077
3078        iamhere("About to call load_mountlist and load_raidtab");
3079        strcpy(bkpinfo->restore_path, MNT_RESTORING);
3080        read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
3081        retval = load_mountlist(mountlist, g_mountlist_fname);
3082        retval += load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3083        iamhere
3084            ("Returned from calling load_mountlist and load_raidtab successfully");
3085
3086        if (argc > 1
3087            && (strcmp(argv[1], "--compare") == 0
3088                || strcmp(argv[1], "--nuke") == 0)) {
3089            if (bkpinfo->backup_media_type == nfs
3090                && !is_this_device_mounted(bkpinfo->nfs_mount)) {
3091                mr_msg(1, "Mounting nfs dir");
3092                sprintf(bkpinfo->isodir, "/tmp/isodir");
3093                run_program_and_log_output("mkdir -p /tmp/isodir", 5);
3094                mr_asprintf(&tmp, "mount %s -t nfs -o nolock /tmp/isodir",
3095                        bkpinfo->nfs_mount);
3096                run_program_and_log_output(tmp, 1);
3097                mr_free(tmp);
3098            }
3099        }
3100
3101
3102        if (retval) {
3103            log_to_screen
3104                (_("Warning - load_raidtab_into_raidlist returned an error"));
3105        }
3106
3107
3108        mr_msg(1, "Send in the clowns.");
3109
3110        if (argc == 2 && strcmp(argv[1], "--partition-only") == 0) {
3111            mr_msg(0, "Partitioning only.");
3112            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3113            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3114            load_mountlist(mountlist, g_mountlist_fname);
3115            res = partition_everything(mountlist);
3116            finish(res);
3117        }
3118
3119        if (argc == 2 && strcmp(argv[1], "--format-only") == 0) {
3120            mr_msg(0, "Formatting only.");
3121            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3122            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3123            load_mountlist(mountlist, g_mountlist_fname);
3124            res = format_everything(mountlist, FALSE, raidlist);
3125            finish(res);
3126        }
3127
3128        if (argc == 2 && strcmp(argv[1], "--stop-lvm-and-raid") == 0) {
3129            mr_msg(0, "Stopping LVM and RAID");
3130            load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3131            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3132            load_mountlist(mountlist, g_mountlist_fname);
3133            res = do_my_funky_lvm_stuff(TRUE, FALSE);
3134            res += stop_all_raid_devices(mountlist);
3135            finish(res);
3136        }
3137
3138        if (argc == 2 && strcmp(argv[1], "--nuke") == 0) {
3139            iamhere("nuking");
3140            retval += nuke_mode(mountlist, raidlist);
3141        } else if (argc == 2 && strcmp(argv[1], "--interactive") == 0) {
3142            iamhere("catchall");
3143            retval += catchall_mode(mountlist, raidlist);
3144        } else if (argc == 2 && strcmp(argv[1], "--compare") == 0) {
3145            iamhere("compare");
3146            retval += compare_mode(mountlist, raidlist);
3147        } else if (argc == 2 && strcmp(argv[1], "--iso") == 0) {
3148            iamhere("iso");
3149            retval = iso_mode(mountlist, raidlist, FALSE);
3150        } else if (argc == 2 && strcmp(argv[1], "--mbr") == 0) {
3151            iamhere("mbr");
3152            retval = mount_all_devices(mountlist, TRUE);
3153            if (!retval) {
3154                retval += run_boot_loader(FALSE);
3155                retval += unmount_all_devices(mountlist);
3156            }
3157            if (retval) {
3158                log_to_screen(_("Failed to write Master Boot Record"));
3159            }
3160        } else if (argc == 2 && strcmp(argv[1], "--isonuke") == 0) {
3161            iamhere("isonuke");
3162            retval = iso_mode(mountlist, raidlist, TRUE);
3163        } else if (argc != 1) {
3164            log_to_screen(_("Invalid parameters"));
3165            paranoid_MR_finish(1);
3166        } else {
3167            iamhere("catchall (no mode specified in command-line call");
3168            retval += catchall_mode(mountlist, raidlist);
3169        }
3170    }
3171
3172    /* clean up at the end */
3173    if (retval) {
3174        if (does_file_exist(MONDO_CACHE"/changed.files")) {
3175            log_to_screen
3176                (_("See "MONDO_CACHE"/changed.files for list of files that have changed."));
3177        }
3178        mvaddstr_and_log_it(g_currentY++,
3179                            0,
3180                            _("Run complete. Errors were reported. Please review the logfile."));
3181    } else {
3182        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
3183            mvaddstr_and_log_it(g_currentY++,
3184                                0,
3185                                _("Run complete. Please remove media and reboot."));
3186        } else {
3187            run_program_and_log_output("sync", FALSE);
3188            if (is_this_device_mounted(MNT_CDROM)) {
3189                res =
3190                    run_program_and_log_output("umount " MNT_CDROM, FALSE);
3191            } else {
3192                res = 0;
3193            }
3194
3195            if (!bkpinfo->please_dont_eject) {
3196                res = eject_device("/dev/cdrom");
3197            }
3198            mvaddstr_and_log_it(g_currentY++,
3199                                0,
3200                                _("Run complete. Please remove media and reboot."));
3201        }
3202    }
3203
3204    // g_I_have_just_nuked is set true by nuke_mode() just before it returns
3205    if (!system("which post-nuke > /dev/null 2> /dev/null")) {
3206      mr_msg(1, "post-nuke found; find out whether we should run it...");
3207      if (g_I_have_just_nuked || does_file_exist("/POST-NUKE-ANYWAY")) {
3208        run_postnuke = TRUE;
3209        mr_msg(1, "Yes, will run post-nuke because in nuke mode or file /POST-NUKE-ANYWAY exists.");
3210      } else if (ask_me_yes_or_no("post-nuke script found. Do you want to run it?")) {
3211        run_postnuke = TRUE;
3212        mr_msg(1, "Yes, will run post-nuke because user interactively asked for it.");
3213      } else {
3214        run_postnuke = FALSE;
3215        mr_msg(1, "No, will not run post-nuke.");
3216      }
3217    } else {
3218      mr_msg(1, "No post-nuke found.");
3219    }
3220    if (run_postnuke) {
3221      log_to_screen("Running post-nuke...");
3222      if (mount_all_devices(mountlist, TRUE)) {
3223        log_to_screen
3224          ("Unable to re-mount partitions for post-nuke stuff");
3225      } else {
3226        mr_msg(1, "Re-mounted partitions for post-nuke stuff");
3227        mr_asprintf(&tmp, "post-nuke %s %d", bkpinfo->restore_path,
3228            retval);
3229        mr_msg(2, "Calling '%s'", tmp);
3230        if ((res = run_program_and_log_output(tmp, 0))) {
3231          log_OS_error(tmp);
3232        }
3233        mr_free(tmp);
3234        mr_msg(1, "post-nuke returned w/ res=%d", res);
3235      }
3236      unmount_all_devices(mountlist);
3237      log_to_screen("I've finished post-nuking.");
3238    }
3239
3240    unlink("/tmp/mondo-run-prog.tmp");
3241    set_signals(FALSE);
3242
3243    log_to_screen
3244        (_("Restore log (%s) copied to /var/log on your hard disk"), MONDO_LOGFILE);
3245    log_to_screen(_("Mondo-restore is exiting (retval=%d)"), retval);
3246
3247    mr_asprintf(&tmp, "umount %s", bkpinfo->isodir);
3248    run_program_and_log_output(tmp, 5);
3249    mr_free(tmp);
3250
3251    mr_free(mountlist);
3252    mr_free(raidlist);
3253    if (am_I_in_disaster_recovery_mode()) {
3254        run_program_and_log_output("mount / -o remount,rw", 2);
3255    }                           // for b0rken distros
3256    mr_asprintf(&tmp, "rm -Rf %s", bkpinfo->tmpdir);
3257    run_program_and_log_output(tmp, FALSE);
3258    mr_free(tmp);
3259
3260    paranoid_MR_finish(retval); // frees global stuff plus bkpinfo
3261    free_libmondo_global_strings(); // it's fine to have this here :) really :)
3262
3263    unlink("/tmp/filelist.full");
3264    unlink("/tmp/filelist.full.gz");
3265
3266    mr_exit(retval, NULL);
3267}
3268
3269/**************************************************************************
3270 *END_MAIN                                                                *
3271 **************************************************************************/
3272
3273
3274/**************************************************************************
3275 *END_MONDO-RESTORE.C                                                     *
3276 **************************************************************************/
3277=======
3278/***************************************************************************
3279$Id: mondorestore.c 1939 2008-05-16 23:29:54Z bruno $
3280restores mondoarchive data
3281***************************************************************************/
3282
3283/**
3284 * @file
3285 * The main file for mondorestore.
3286 */
3287
3288/**************************************************************************
3289 * #include statements                                                    *
3290 **************************************************************************/
3291#include <pthread.h>
3292#include "my-stuff.h"
3293#include "../common/mondostructures.h"
3294#include "../common/libmondo.h"
3295#include "mr-externs.h"
3296#include "mondo-restore.h"
3297#include "mondorestore.h"
3298#include "mondo-rstr-compare-EXT.h"
3299#include "mondo-rstr-tools-EXT.h"
3300
3301extern void twenty_seconds_til_yikes(void);
3302
3303/* Reference to global bkpinfo */
3304struct s_bkpinfo *bkpinfo;
3305
3306
3307/* For use in other programs (ex. XMondo) */
3308#ifdef MONDORESTORE_MODULE
3309#define main __mondorestore_main
3310#define g_ISO_restore_mode __mondorestore_g_ISO_restore_mode
3311#endif
3312
3313//static char cvsid[] = "$Id: mondorestore.c 1939 2008-05-16 23:29:54Z bruno $";
3314
3315/**************************************************************************
3316 * Globals                                                                *
3317 **************************************************************************/
3318extern char *g_tmpfs_mountpt;   // declared in libmondo-tools.c
3319extern bool g_text_mode;
3320extern FILE *g_fprep;
3321extern double g_kernel_version;
3322extern int g_partition_table_locked_up;
3323extern int g_noof_rows;
3324
3325extern int partition_everything(struct mountlist_itself *mountlist);
3326
3327
3328/**
3329 * @name Restore-Time Globals
3330 * @ingroup globalGroup
3331 * @{
3332 */
3333
3334/**
3335 * If TRUE, then we're restoring from ISOs or an NFS server.
3336 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
3337 */
3338bool g_ISO_restore_mode = FALSE;    /* are we in Iso Mode? */
3339
3340/**
3341 * If TRUE, then we have had a successful "nuke" restore.
3342 */
3343bool g_I_have_just_nuked = FALSE;
3344
3345/**
3346 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
3347 */
3348char *g_isodir_device;
3349
3350/**
3351 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
3352 */
3353char *g_isodir_format;
3354
3355/**
3356 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
3357 */
3358char *g_biggielist_txt;
3359
3360/**
3361 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
3362 * the current archive set.
3363 */
3364char *g_filelist_full;
3365
3366/**
3367 * The location of a file containing a list of the devices that were archived
3368 * as images, not as individual files.
3369 */
3370char *g_filelist_imagedevs;
3371
3372/**
3373 * The location of a file containing a list of imagedevs to actually restore.
3374 * @see g_filelist_imagedevs
3375 */
3376char *g_imagedevs_restthese;
3377
3378/**
3379 * The location of 'mondo-restore.cfg', containing the metadata
3380 * information for this backup.
3381 */
3382char *g_mondo_cfg_file;
3383
3384/**
3385 * The location of 'mountlist.txt', containing the information on the
3386 * user's partitions and hard drives.
3387 */
3388char *g_mountlist_fname;
3389
3390/**
3391 * Mondo's home directory during backup. Unused in mondorestore; included
3392 * to avoid link errors.
3393 */
3394char *g_mondo_home;
3395
3396extern char *g_getfacl;
3397extern char *g_getfattr;
3398
3399/* @} - end of "Restore-Time Globals" in globalGroup */
3400
3401
3402
3403extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
3404                                 char direction);
3405
3406
3407
3408/**************************************************************************
3409 * COMPAQ PROLIANT Stuff:  needs some special help                        *
3410**************************************************************************/
3411
3412/**
3413 * The message to display if we detect that the user is using a Compaq Proliant.
3414 */
3415#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."
3416
3417
3418
3419
3420/**
3421 * Allow the user to modify the mountlist before we partition & format their drives.
3422 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
3423 * @param mountlist The mountlist to let the user modify.
3424 * @param raidlist The raidlist that goes with @p mountlist.
3425 * @return 0 for success, nonzero for failure.
3426 * @ingroup restoreGuiGroup
3427 */
3428int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
3429                                struct raidlist_itself *raidlist)
3430{
3431    int retval = 0, res = 0;
3432
3433    log_msg(2, "let_user_edit_the_mountlist() --- starting");
3434
3435    assert(bkpinfo != NULL);
3436    assert(mountlist != NULL);
3437    assert(raidlist != NULL);
3438    if (!bkpinfo->disaster_recovery) {
3439        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
3440        log_msg(2, "I guess you're testing edit_mountlist()");
3441    }
3442    if (!does_file_exist(g_mountlist_fname)) {
3443        log_to_screen(g_mountlist_fname);
3444        log_to_screen("does not exist");
3445        return (1);
3446    }
3447
3448    retval = load_mountlist(mountlist, g_mountlist_fname);
3449    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
3450    if (retval) {
3451        log_to_screen
3452            ("Warning - load_raidtab_into_raidlist returned an error");
3453    }
3454    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
3455    if (res) {
3456        return (1);
3457    }
3458
3459    save_mountlist_to_disk(mountlist, g_mountlist_fname);
3460    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
3461
3462    log_to_screen("I have finished editing the mountlist for you.");
3463
3464    return (retval);
3465}
3466
3467
3468
3469
3470
3471/**
3472 * Determine whether @p mountlist contains a Compaq diagnostic partition.
3473 * @param mountlist The mountlist to examine.
3474 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
3475 * @ingroup restoreUtilityGroup
3476 */
3477bool
3478partition_table_contains_Compaq_diagnostic_partition(struct
3479                                                     mountlist_itself *
3480                                                     mountlist)
3481{
3482    int i;
3483
3484    assert(mountlist != NULL);
3485
3486    for (i = 0; i < mountlist->entries; i++) {
3487        if (strstr(mountlist->el[i].format, "ompaq")) {
3488            log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
3489                    i, mountlist->el[i].device, mountlist->el[i].format);
3490
3491            return (TRUE);
3492        }
3493    }
3494    return (FALSE);
3495}
3496
3497/**************************************************************************
3498 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION                *
3499 **************************************************************************/
3500
3501
3502/**
3503 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
3504 * @note This function does not actually check for the presence of a Compaq partition.
3505 * @ingroup restoreUtilityGroup
3506 */
3507void offer_to_abort_because_Compaq_Proliants_suck(void)
3508{
3509    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
3510    if (ask_me_yes_or_no
3511        ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
3512    {
3513        fatal_error
3514            ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
3515    }
3516}
3517
3518/**************************************************************************
3519 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK                        *
3520 **************************************************************************/
3521
3522
3523
3524/**
3525 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
3526 * @param bkpinfo The backup information structure. Most fields are used.
3527 * @param mountlist The mountlist containing information about the user's partitions.
3528 * @param raidlist The raidlist to go with @p mountlist.
3529 * @return The return code from the mode function called.
3530 * @ingroup restoreGroup
3531 */
3532int
3533catchall_mode(struct mountlist_itself *mountlist,
3534              struct raidlist_itself *raidlist)
3535{
3536    char c, *tmp;
3537    int retval = 0;
3538
3539    iamhere("inside catchall");
3540    assert(bkpinfo != NULL);
3541    assert(mountlist != NULL);
3542    assert(raidlist != NULL);
3543    malloc_string(tmp);
3544    iamhere("pre wrm");
3545    c = which_restore_mode();
3546    iamhere("post wrm");
3547    if (c == 'I' || c == 'N' || c == 'C') {
3548        interactively_obtain_media_parameters_from_user(FALSE);
3549    } else {
3550        popup_and_OK("No restoring or comparing will take place today.");
3551        if (is_this_device_mounted("/mnt/cdrom")) {
3552            run_program_and_log_output("umount /mnt/cdrom", FALSE);
3553        }
3554        if (g_ISO_restore_mode) {
3555            sprintf(tmp, "umount %s", bkpinfo->isodir);
3556            run_program_and_log_output(tmp, FALSE);
3557        }
3558        paranoid_MR_finish(0);
3559    }
3560
3561    iamhere("post int");
3562
3563    if (bkpinfo->backup_media_type == iso) {
3564        if (iso_fiddly_bits((c == 'N') ? TRUE : FALSE)) {
3565            log_msg(2,
3566                    "catchall_mode --- iso_fiddly_bits returned w/ error");
3567            return (1);
3568        } else {
3569            log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
3570        }
3571    }
3572
3573    if (c == 'I') {
3574        log_msg(2, "IM selected");
3575        retval += interactive_mode(mountlist, raidlist);
3576    } else if (c == 'N') {
3577        log_msg(2, "NM selected");
3578        retval += nuke_mode(mountlist, raidlist);
3579    } else if (c == 'C') {
3580        log_msg(2, "CM selected");
3581        retval += compare_mode(mountlist, raidlist);
3582    }
3583    paranoid_free(tmp);
3584    return (retval);
3585}
3586
3587/**************************************************************************
3588 *END_CATCHALL_MODE                                                      *
3589 **************************************************************************/
3590
3591/**************************************************************************
3592 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
3593 **************************************************************************/
3594
3595
3596/**
3597 * Locate an executable in the directory structure rooted at @p restg.
3598 * @param out_path Where to put the executable.
3599 * @param fname The basename of the executable.
3600 * @param restg The directory structure to look in.
3601 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
3602 * @ingroup restoreUtilityGroup
3603 */
3604void
3605find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
3606                                                    char *fname,
3607                                                    char *restg)
3608{
3609    assert(out_path != NULL);
3610    assert_string_is_neither_NULL_nor_zerolength(fname);
3611
3612    sprintf(out_path, "%s/sbin/%s", restg, fname);
3613    if (does_file_exist(out_path)) {
3614        sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
3615        if (does_file_exist(out_path)) {
3616            sprintf(out_path, "%s/bin/%s", restg, fname);
3617            if (does_file_exist(out_path)) {
3618                sprintf(out_path, "%s/usr/bin/%s", restg, fname);
3619                if (does_file_exist(out_path)) {
3620                    strcpy(out_path, fname);
3621                }
3622            }
3623        }
3624    }
3625}
3626
3627/**************************************************************************
3628 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
3629 **************************************************************************/
3630
3631static void clean_blkid() {
3632
3633    char *tmp1 = NULL;
3634
3635    /* Clean up blkid cache file if they exist */
3636    asprintf(&tmp1,"%s/etc/blkid.tab",bkpinfo->restore_path);
3637    (void)unlink(tmp1);
3638    paranoid_free(tmp1);
3639    asprintf(&tmp1,"%s/etc/blkid.tab.old",bkpinfo->restore_path);
3640    (void)unlink(tmp1);
3641    paranoid_free(tmp1);
3642}
3643
3644
3645
3646
3647/**
3648 * @addtogroup restoreGroup
3649 * @{
3650 */
3651/**
3652 * Restore the user's data, in a disaster recovery situation, prompting the
3653 * user about whether or not to do every step.
3654 * The user can edit the mountlist, choose files to restore, etc.
3655 * @param bkpinfo The backup information structure. Most fields are used.
3656 * @param mountlist The mountlist containing information about the user's partitions.
3657 * @param raidlist The raidlist to go with @p mountlist.
3658 * @return 0 for success, or the number of errors encountered.
3659 */
3660int
3661interactive_mode(struct mountlist_itself *mountlist,
3662                 struct raidlist_itself *raidlist)
3663{
3664    int retval = 0;
3665    int res;
3666    int ptn_errs = 0;
3667    int fmt_errs = 0;
3668
3669    bool done;
3670    bool restore_all;
3671
3672  /** needs malloc **********/
3673    char *tmp;
3674    char *fstab_fname;
3675    char *old_restpath;
3676
3677    struct s_node *filelist;
3678
3679    /* try to partition and format */
3680
3681    log_msg(2, "interactive_mode --- starting (great, assertions OK)");
3682
3683    malloc_string(tmp);
3684    malloc_string(fstab_fname);
3685    malloc_string(old_restpath);
3686    assert(bkpinfo != NULL);
3687    assert(mountlist != NULL);
3688    assert(raidlist != NULL);
3689
3690    log_msg(2, "interactive_mode --- assertions OK");
3691
3692    if (g_text_mode) {
3693        if (!ask_me_yes_or_no
3694            ("Interactive Mode + textonly = experimental! Proceed anyway?"))
3695        {
3696            fatal_error("Wise move.");
3697        }
3698    }
3699
3700    iamhere("About to load config file");
3701    get_cfg_file_from_archive_or_bust();
3702    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
3703    iamhere("Done loading config file; resizing ML");
3704    if (bkpinfo->backup_media_type == nfs) {
3705        strcpy(tmp, bkpinfo->prefix);
3706        if (popup_and_get_string
3707            ("Prefix", "Prefix of your ISO images ?", tmp, MAX_STR_LEN / 4)) {
3708            strcpy(bkpinfo->prefix, tmp);
3709            log_msg(1, "Prefix set to %s",bkpinfo->prefix);
3710        }
3711    }
3712   
3713#ifdef __FreeBSD__
3714    if (strstr
3715        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
3716         "noresize"))
3717#else
3718    if (strstr
3719        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
3720         "noresize"))
3721#endif
3722    {
3723        log_msg(1, "Not resizing mountlist.");
3724    } else {
3725        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
3726    }
3727    for (done = FALSE; !done;) {
3728        iamhere("About to edit mountlist");
3729        if (g_text_mode) {
3730            save_mountlist_to_disk(mountlist, g_mountlist_fname);
3731            sprintf(tmp, "%s %s", find_my_editor(), g_mountlist_fname);
3732            res = system(tmp);
3733            load_mountlist(mountlist, g_mountlist_fname);
3734        } else {
3735            res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
3736        }
3737        iamhere("Finished editing mountlist");
3738        if (res) {
3739            paranoid_MR_finish(1);
3740        }
3741        log_msg(2, "Proceeding...");
3742        save_mountlist_to_disk(mountlist, g_mountlist_fname);
3743        save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
3744        mvaddstr_and_log_it(1, 30, "Restoring Interactively");
3745        if (bkpinfo->differential) {
3746            log_to_screen("Because this is a differential backup, disk");
3747            log_to_screen
3748                (" partitioning and formatting will not take place.");
3749            done = TRUE;
3750        } else {
3751            if (ask_me_yes_or_no
3752                ("Do you want to erase and partition your hard drives?")) {
3753                if (partition_table_contains_Compaq_diagnostic_partition
3754                    (mountlist)) {
3755                    offer_to_abort_because_Compaq_Proliants_suck();
3756                    done = TRUE;
3757                } else {
3758                    twenty_seconds_til_yikes();
3759                    g_fprep = fopen("/tmp/prep.sh", "w");
3760                    ptn_errs = partition_everything(mountlist);
3761                    if (ptn_errs) {
3762                        log_to_screen
3763                            ("Warning. Errors occurred during disk partitioning.");
3764                    }
3765
3766                    fmt_errs = format_everything(mountlist, FALSE, raidlist);
3767                    if (!fmt_errs) {
3768                        log_to_screen
3769                            ("Errors during disk partitioning were handled OK.");
3770                        log_to_screen
3771                            ("Partitions were formatted OK despite those errors.");
3772                        ptn_errs = 0;
3773                    }
3774                    if (!ptn_errs && !fmt_errs) {
3775                        done = TRUE;
3776                    }
3777                }
3778                paranoid_fclose(g_fprep);
3779            } else {
3780                mvaddstr_and_log_it(g_currentY++, 0,
3781                                    "User opted not to partition the devices");
3782                if (ask_me_yes_or_no
3783                    ("Do you want to format your hard drives?")) {
3784                    fmt_errs = format_everything(mountlist, TRUE, raidlist);
3785                    if (!fmt_errs) {
3786                        done = TRUE;
3787                    }
3788                } else {
3789                    ptn_errs = fmt_errs = 0;
3790                    done = TRUE;
3791                }
3792            }
3793            if (fmt_errs) {
3794                mvaddstr_and_log_it(g_currentY++,
3795                                    0,
3796                                    "Errors occurred. Please repartition and format drives manually.");
3797                done = FALSE;
3798            }
3799            if (ptn_errs & !fmt_errs) {
3800                mvaddstr_and_log_it(g_currentY++,
3801                                    0,
3802                                    "Errors occurred during partitioning. Formatting, however, went OK.");
3803                done = TRUE;
3804            }
3805            if (!done) {
3806                if (!ask_me_yes_or_no("Re-edit the mountlist?")) {
3807                    retval++;
3808                    goto end_of_func;
3809                }
3810            }
3811        }
3812    }
3813
3814    /* mount */
3815    if (mount_all_devices(mountlist, TRUE)) {
3816        unmount_all_devices(mountlist);
3817        retval++;
3818        goto end_of_func;
3819    }
3820    /* restore */
3821    if ((restore_all =
3822         ask_me_yes_or_no("Do you want me to restore all of your data?")))
3823    {
3824        log_msg(1, "Restoring all data");
3825        retval += restore_everything(NULL);
3826    } else
3827        if ((restore_all =
3828             ask_me_yes_or_no
3829             ("Do you want me to restore _some_ of your data?"))) {
3830        strcpy(old_restpath, bkpinfo->restore_path);
3831        for (done = FALSE; !done;) {
3832            unlink("/tmp/filelist.full");
3833            filelist = process_filelist_and_biggielist();
3834            /* Now you have /tmp/tmpfs/filelist.restore-these and /tmp/tmpfs/biggielist.restore-these;
3835               the former is a list of regular files; the latter, biggiefiles and imagedevs.
3836             */
3837            if (filelist) {
3838              gotos_suck:
3839                strcpy(tmp, old_restpath);
3840// (NB: %s is where your filesystem is mounted now, by default)", MNT_RESTORING);
3841                if (popup_and_get_string
3842                    ("Restore path", "Restore files to where?", tmp,
3843                     MAX_STR_LEN / 4)) {
3844                    if (!strcmp(tmp, "/")) {
3845                        if (!ask_me_yes_or_no("Are you sure?")) {
3846                            goto gotos_suck;
3847                        }
3848                        tmp[0] = '\0';  // so we restore to [blank]/file/name :)
3849                    }
3850                    strcpy(bkpinfo->restore_path, tmp);
3851                    log_msg(1, "Restoring subset");
3852                    retval += restore_everything(filelist);
3853                    free_filelist(filelist);
3854                } else {
3855                    strcpy(bkpinfo->restore_path, old_restpath);
3856                    free_filelist(filelist);
3857                }
3858                if (!ask_me_yes_or_no
3859                    ("Restore another subset of your backup?")) {
3860                    done = TRUE;
3861                }
3862            } else {
3863                done = TRUE;
3864            }
3865        }
3866        strcpy(old_restpath, bkpinfo->restore_path);
3867    } else {
3868        mvaddstr_and_log_it(g_currentY++,
3869                            0,
3870                            "User opted not to restore any data.                                  ");
3871    }
3872    if (retval) {
3873        mvaddstr_and_log_it(g_currentY++,
3874                            0,
3875                            "Errors occurred during the restore phase.            ");
3876    }
3877
3878    if (ask_me_yes_or_no("Initialize the boot loader?")) {
3879        run_boot_loader(TRUE);
3880    } else {
3881        mvaddstr_and_log_it(g_currentY++,
3882                            0,
3883                            "User opted not to initialize the boot loader.");
3884    }
3885
3886    clean_blkid();
3887    protect_against_braindead_sysadmins();
3888    retval += unmount_all_devices(mountlist);
3889    /*  if (restore_some || restore_all || */
3890    if (ask_me_yes_or_no
3891        ("Label/Identify your ext2 and ext3 partitions if necessary?")) {
3892        mvaddstr_and_log_it(g_currentY, 0,
3893                            "Using tune2fs to identify your ext2,3 partitions");
3894        if (does_file_exist("/tmp/fstab.new")) {
3895            strcpy(fstab_fname, "/tmp/fstab.new");
3896        } else {
3897            strcpy(fstab_fname, "/tmp/fstab");
3898        }
3899        sprintf(tmp,
3900                "label-partitions-as-necessary %s < %s >> %s 2>> %s",
3901                g_mountlist_fname, fstab_fname, MONDO_LOGFILE,
3902                MONDO_LOGFILE);
3903        res = system(tmp);
3904        if (res) {
3905            log_to_screen
3906                ("label-partitions-as-necessary returned an error");
3907            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
3908        } else {
3909            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
3910        }
3911        retval += res;
3912    }
3913
3914    iamhere("About to leave interactive_mode()");
3915    if (retval) {
3916        mvaddstr_and_log_it(g_currentY++,
3917                            0,
3918                            "Warning - errors occurred during the restore phase.");
3919    }
3920  end_of_func:
3921    paranoid_free(tmp);
3922    paranoid_free(fstab_fname);
3923    paranoid_free(old_restpath);
3924    iamhere("Leaving interactive_mode()");
3925    return (retval);
3926}
3927
3928/**************************************************************************
3929 *END_INTERACTIVE_MODE                                                    *
3930 **************************************************************************/
3931
3932
3933
3934/**
3935 * Run an arbitrary restore mode (prompt the user), but from ISO images
3936 * instead of real media.
3937 * @param mountlist The mountlist containing information about the user's partitions.
3938 * @param raidlist The raidlist that goes with @p mountlist.
3939 * @param nuke_me_please If TRUE, we plan to run Nuke Mode.
3940 * @return 0 for success, or the number of errors encountered.
3941 */
3942int
3943iso_mode(struct mountlist_itself *mountlist,
3944         struct raidlist_itself *raidlist, bool nuke_me_please)
3945{
3946    char c;
3947    int retval = 0;
3948
3949    assert(mountlist != NULL);
3950    assert(raidlist != NULL);
3951    if (iso_fiddly_bits(nuke_me_please)) {
3952        log_msg(1, "iso_mode --- returning w/ error");
3953        return (1);
3954    } else {
3955        c = which_restore_mode();
3956        if (c == 'I' || c == 'N' || c == 'C') {
3957            interactively_obtain_media_parameters_from_user(FALSE);
3958        }
3959        if (c == 'I') {
3960            retval += interactive_mode(mountlist, raidlist);
3961        } else if (c == 'N') {
3962            retval += nuke_mode(mountlist, raidlist);
3963        } else if (c == 'C') {
3964            retval += compare_mode(mountlist, raidlist);
3965        } else {
3966            log_to_screen("OK, I shan't restore/compare any files.");
3967        }
3968    }
3969    if (is_this_device_mounted(MNT_CDROM)) {
3970        paranoid_system("umount " MNT_CDROM);
3971    }
3972//  if (! already_mounted)
3973//    {
3974    if (system("umount /tmp/isodir 2> /dev/null")) {
3975        log_to_screen
3976            ("WARNING - unable to unmount device where the ISO files are stored.");
3977    }
3978//    }
3979    return (retval);
3980}
3981
3982/**************************************************************************
3983 *END_ISO_MODE                                                            *
3984 **************************************************************************/
3985
3986
3987/*            MONDO - saving your a$$ since Feb 18th, 2000            */
3988
3989
3990
3991
3992/**
3993 * Restore the user's data automatically (no prompts), after a twenty-second
3994 * warning period.
3995 * @param bkpinfo The backup information structure. Most fields are used.
3996 * @param mountlist The mountlist containing information about the user's partitions.
3997 * @param raidlist The raidlist that goes with @p mountlist.
3998 * @return 0 for success, or the number of errors encountered.
3999 * @warning <b><i>THIS WILL ERASE ALL EXISTING DATA!</i></b>
4000 */
4001int
4002nuke_mode(struct mountlist_itself *mountlist,
4003          struct raidlist_itself *raidlist)
4004{
4005    int retval = 0;
4006    int res = 0;
4007    bool boot_loader_installed = FALSE;
4008  /** malloc **/
4009    char tmp[MAX_STR_LEN], tmpA[MAX_STR_LEN], tmpB[MAX_STR_LEN],
4010        tmpC[MAX_STR_LEN];
4011
4012    assert(bkpinfo != NULL);
4013    assert(mountlist != NULL);
4014    assert(raidlist != NULL);
4015
4016    log_msg(2, "nuke_mode --- starting");
4017
4018    get_cfg_file_from_archive_or_bust();
4019    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo updated the mountlist
4020#ifdef __FreeBSD__
4021    if (strstr
4022        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
4023         "noresize"))
4024#else
4025    if (strstr
4026        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
4027         "noresize"))
4028#endif
4029    {
4030        log_msg(2, "Not resizing mountlist.");
4031    } else {
4032        resize_mountlist_proportionately_to_suit_new_drives(mountlist);
4033    }
4034    if (!evaluate_mountlist(mountlist, tmpA, tmpB, tmpC)) {
4035        sprintf(tmp,
4036                "Mountlist analyzed. Result: \"%s %s %s\" Switch to Interactive Mode?",
4037                tmpA, tmpB, tmpC);
4038        if (ask_me_yes_or_no(tmp)) {
4039            retval = interactive_mode(mountlist, raidlist);
4040            goto after_the_nuke;
4041        } else {
4042            fatal_error("Nuke Mode aborted. ");
4043        }
4044    }
4045    save_mountlist_to_disk(mountlist, g_mountlist_fname);
4046    mvaddstr_and_log_it(1, 30, "Restoring Automatically");
4047    if (bkpinfo->differential) {
4048        log_to_screen("Because this is a differential backup, disk");
4049        log_to_screen("partitioning and formatting will not take place.");
4050        res = 0;
4051    } else {
4052        if (partition_table_contains_Compaq_diagnostic_partition
4053            (mountlist)) {
4054            offer_to_abort_because_Compaq_Proliants_suck();
4055        } else {
4056            twenty_seconds_til_yikes();
4057            g_fprep = fopen("/tmp/prep.sh", "w");
4058#ifdef __FreeBSD__
4059            if (strstr
4060                (call_program_and_get_last_line_of_output
4061                 ("cat /tmp/cmdline"), "nopart"))
4062#else
4063            if (strstr
4064                (call_program_and_get_last_line_of_output
4065                 ("cat /proc/cmdline"), "nopart"))
4066#endif
4067            {
4068                log_msg(2,
4069                        "Not partitioning drives due to 'nopart' option.");
4070                res = 0;
4071            } else {
4072                res = partition_everything(mountlist);
4073                if (res) {
4074                    log_to_screen
4075                        ("Warning. Errors occurred during partitioning.");
4076                    res = 0;
4077                }
4078            }
4079            retval += res;
4080            if (!res) {
4081                log_to_screen("Preparing to format your disk(s)");
4082                sleep(1);
4083                system("sync");
4084                log_to_screen("Please wait. This may take a few minutes.");
4085                res += format_everything(mountlist, FALSE, raidlist);
4086            }
4087            paranoid_fclose(g_fprep);
4088        }
4089    }
4090    retval += res;
4091    if (res) {
4092        mvaddstr_and_log_it(g_currentY++,
4093                            0,
4094                            "Failed to partition and/or format your hard drives.");
4095
4096        if (ask_me_yes_or_no("Try in interactive mode instead?")) {
4097            retval = interactive_mode(mountlist, raidlist);
4098            goto after_the_nuke;
4099        } else
4100            if (!ask_me_yes_or_no
4101                ("Would you like to try to proceed anyway?")) {
4102            return (retval);
4103        }
4104    }
4105    retval = mount_all_devices(mountlist, TRUE);
4106    if (retval) {
4107        unmount_all_devices(mountlist);
4108        log_to_screen
4109            ("Unable to mount all partitions. Sorry, I cannot proceed.");
4110        return (retval);
4111    }
4112    iamhere("Restoring everything");
4113    retval += restore_everything(NULL);
4114    if (!run_boot_loader(FALSE)) {
4115        log_msg(1,
4116                "Great! Boot loader was installed. No need for msg at end.");
4117        boot_loader_installed = TRUE;
4118    }
4119    clean_blkid();
4120    protect_against_braindead_sysadmins();
4121    retval += unmount_all_devices(mountlist);
4122    mvaddstr_and_log_it(g_currentY,
4123                        0,
4124                        "Using tune2fs to identify your ext2,3 partitions");
4125
4126    sprintf(tmp, "label-partitions-as-necessary %s < /tmp/fstab",
4127            g_mountlist_fname);
4128    res = run_program_and_log_output(tmp, TRUE);
4129    if (res) {
4130        log_to_screen("label-partitions-as-necessary returned an error");
4131        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
4132    } else {
4133        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
4134    }
4135    retval += res;
4136
4137  after_the_nuke:
4138    if (retval) {
4139        log_to_screen("Errors occurred during the nuke phase.");
4140    } else if (strstr(call_program_and_get_last_line_of_output("cat /proc/cmdline"), "RESTORE")) {
4141        log_to_screen
4142            ("PC was restored successfully. Thank you for using Mondo Rescue.");
4143        log_to_screen
4144            ("Please visit our website at http://www.mondorescue.org for more information.");
4145    } else {
4146        strcpy(tmp,"Mondo has restored your system.\n\nPlease wait for the command prompt. Then remove the backup media and reboot.\n\nPlease visit our website at http://www.mondorescue.org for more information.");
4147            popup_and_OK(tmp);
4148        log_to_screen
4149          ("Mondo has restored your system. Please wait for the command prompt.");
4150        log_to_screen
4151            ("Then remove the backup media and reboot.");
4152        log_to_screen
4153            ("Please visit our website at http://www.mondorescue.org for more information.");
4154    }
4155    g_I_have_just_nuked = TRUE;
4156/*
4157  if (!boot_loader_installed && !does_file_exist(DO_MBR_PLEASE))
4158    {
4159      log_to_screen("PLEASE RUN 'mondorestore --mbr' NOW TO INITIALIZE YOUR BOOT SECTOR");
4160      write_one_liner_data_file(DO_MBR_PLEASE, "mondorestore --mbr");
4161    }
4162*/
4163    return (retval);
4164}
4165
4166/**************************************************************************
4167 *END_NUKE_MODE                                                           *
4168 **************************************************************************/
4169
4170
4171
4172/**
4173 * Restore the user's data (or a subset of it) to the live filesystem.
4174 * This should not be called if we're booted from CD!
4175 * @param bkpinfo The backup information structure. Most fields are used.
4176 * @return 0 for success, or the number of errors encountered.
4177 */
4178int restore_to_live_filesystem()
4179{
4180    int retval = 0;
4181
4182  /** malloc **/
4183    char *old_restpath;
4184
4185    struct mountlist_itself *mountlist;
4186//  static
4187    struct raidlist_itself *raidlist;
4188    struct s_node *filelist;
4189
4190    log_msg(1, "restore_to_live_filesystem() - starting");
4191    assert(bkpinfo != NULL);
4192    malloc_string(old_restpath);
4193    mountlist = malloc(sizeof(struct mountlist_itself));
4194    raidlist = malloc(sizeof(struct raidlist_itself));
4195    if (!mountlist || !raidlist) {
4196        fatal_error("Cannot malloc() mountlist and/or raidlist");
4197    }
4198
4199    strcpy(bkpinfo->restore_path, "/");
4200    if (!g_restoring_live_from_cd && !g_restoring_live_from_nfs) {
4201        popup_and_OK
4202            ("Please insert tape/CD/USB Key, then hit 'OK' to continue.");
4203        sleep(1);
4204    }
4205    if (!g_restoring_live_from_nfs) {
4206        interactively_obtain_media_parameters_from_user(FALSE);
4207    }
4208    log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
4209    if (!bkpinfo->media_device[0]) {
4210        log_msg(2, "Warning - failed to find media dev");
4211    }
4212
4213
4214    log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
4215
4216    open_evalcall_form("Thinking...");
4217
4218    get_cfg_file_from_archive_or_bust();
4219    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
4220    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
4221
4222    close_evalcall_form();
4223    retval = load_mountlist(mountlist, g_mountlist_fname);
4224    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
4225
4226    if (!g_restoring_live_from_nfs && (filelist = process_filelist_and_biggielist())) {
4227        save_filelist(filelist, "/tmp/selected-files.txt");
4228        strcpy(old_restpath, bkpinfo->restore_path);
4229        if (popup_and_get_string("Restore path",
4230                                 "Restore files to where? )",
4231                                 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
4232            iamhere("Restoring everything");
4233            retval += restore_everything(filelist);
4234            free_filelist(filelist);
4235            strcpy(bkpinfo->restore_path, old_restpath);
4236        } else {
4237            free_filelist(filelist);
4238        }
4239        strcpy(bkpinfo->restore_path, old_restpath);
4240    } else {
4241        retval += restore_everything(NULL);
4242    }
4243    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
4244        log_msg(2,
4245                "Tape : I don't need to unmount or eject the CD-ROM.");
4246    } else {
4247        run_program_and_log_output("umount " MNT_CDROM, FALSE);
4248        if (!bkpinfo->please_dont_eject) {
4249            eject_device(bkpinfo->media_device);
4250        }
4251    }
4252    run_program_and_log_output("umount " MNT_CDROM, FALSE);
4253    if (!bkpinfo->please_dont_eject) {
4254        eject_device(bkpinfo->media_device);
4255    }
4256    paranoid_free(old_restpath);
4257    free(mountlist);
4258    free(raidlist);
4259    return (retval);
4260}
4261
4262/**************************************************************************
4263 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
4264 **************************************************************************/
4265
4266/* @} - end of restoreGroup */
4267
4268
4269#include <utime.h>
4270/**
4271 * @addtogroup LLrestoreGroup
4272 * @{
4273 */
4274/**
4275 * Restore biggiefile @p bigfileno from the currently mounted CD.
4276 * @param bkpinfo The backup information structure. Fields used:
4277 * - @c bkpinfo->backup_media_type
4278 * - @c bkpinfo->restore_path
4279 * @param bigfileno The biggiefile number (starting from 0) to restore.
4280 * @param filelist The node structure containing the list of files to restore.
4281 * If the biggiefile is not in this list, it will be skipped (return value will
4282 * still indicate success).
4283 * @return 0 for success (or skip), nonzero for failure.
4284 */
4285int
4286restore_a_biggiefile_from_CD(long bigfileno,
4287                             struct s_node *filelist,
4288                             char *pathname_of_last_file_restored)
4289{
4290    FILE *fin;
4291    FILE *fout;
4292    FILE *fbzip2;
4293
4294  /** malloc ***/
4295    char *checksum, *outfile_fname, *tmp, *bzip2_command,
4296        *ntfsprog_command, *suffix, *sz_devfile;
4297    char *bigblk;
4298    char *p;
4299    int retval = 0;
4300    int finished = FALSE;
4301    long sliceno;
4302    long siz;
4303    char ntfsprog_fifo[MAX_STR_LEN];
4304    char *file_to_openout = NULL;
4305    struct s_filename_and_lstat_info biggiestruct;
4306    struct utimbuf the_utime_buf, *ubuf;
4307    bool use_ntfsprog_hack = FALSE;
4308    pid_t pid;
4309    int res = 0;
4310    int old_loglevel;
4311    char sz_msg[MAX_STR_LEN];
4312    struct s_node *node;
4313
4314    old_loglevel = g_loglevel;
4315    ubuf = &the_utime_buf;
4316    assert(bkpinfo != NULL);
4317
4318    malloc_string(checksum);
4319    malloc_string(outfile_fname);
4320    malloc_string(tmp);
4321    malloc_string(bzip2_command);
4322    malloc_string(ntfsprog_command);
4323    malloc_string(suffix);
4324    malloc_string(sz_devfile);
4325
4326    pathname_of_last_file_restored[0] = '\0';
4327    if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
4328        fatal_error("Cannot malloc bigblk");
4329    }
4330
4331    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
4332        log_to_screen("Cannot even open bigfile's info file");
4333        return (1);
4334    }
4335
4336    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
4337    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
4338        sizeof(biggiestruct)) {
4339        log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
4340                bigfileno + 1);
4341    }
4342    paranoid_fclose(fin);
4343
4344    strcpy(checksum, biggiestruct.checksum);
4345
4346    if (!checksum[0]) {
4347        sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
4348                bigfileno + 1);
4349        log_msg(3, tmp);
4350        p = checksum;
4351    }
4352
4353    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
4354    {
4355        strcpy(outfile_fname, biggiestruct.filename);
4356    } else {
4357        sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
4358                biggiestruct.filename);
4359    }
4360
4361    /* skip file if we have a selective restore subset & it doesn't match */
4362    if (filelist != NULL) {
4363        node = find_string_at_node(filelist, biggiestruct.filename);
4364        if (!node) {
4365            log_msg(0, "Skipping %s (name isn't in filelist)",
4366                    biggiestruct.filename);
4367            pathname_of_last_file_restored[0] = '\0';
4368            return (0);
4369        } else if (!(node->selected)) {
4370            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
4371                    biggiestruct.filename);
4372            pathname_of_last_file_restored[0] = '\0';
4373            return (0);
4374        }
4375    }
4376    /* otherwise, continue */
4377
4378    log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
4379    if (biggiestruct.use_ntfsprog) {
4380        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
4381            log_msg(1,
4382                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
4383            log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
4384            biggiestruct.use_ntfsprog = FALSE;
4385        }
4386    }
4387
4388    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
4389//  if (!strncmp ( biggiestruct.filename, "/dev/", 5))
4390    {
4391        g_loglevel = 4;
4392        use_ntfsprog_hack = TRUE;
4393        log_msg(2,
4394                "Calling ntfsclone in background because %s is an NTFS /dev entry",
4395                outfile_fname);
4396        sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
4397                (int) (random() % 32768));
4398        mkfifo(sz_devfile, 0x770);
4399        strcpy(ntfsprog_fifo, sz_devfile);
4400        file_to_openout = ntfsprog_fifo;
4401        switch (pid = fork()) {
4402        case -1:
4403            fatal_error("Fork failure");
4404        case 0:
4405            log_msg(3,
4406                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
4407                    biggiestruct.filename, ntfsprog_fifo);
4408            res =
4409                feed_outfrom_ntfsprog(biggiestruct.filename,
4410                                       ntfsprog_fifo);
4411//          log_msg(3, "CHILD - fip - exiting");
4412            exit(res);
4413            break;
4414        default:
4415            log_msg(3,
4416                    "feed_into_ntfsprog() called in background --- pid=%ld",
4417                    (long int) (pid));
4418        }
4419    } else {
4420        use_ntfsprog_hack = FALSE;
4421        ntfsprog_fifo[0] = '\0';
4422        file_to_openout = outfile_fname;
4423        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
4424        {
4425            make_hole_for_file(outfile_fname);
4426        }
4427    }
4428
4429    sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
4430            outfile_fname);
4431    log_msg(2, tmp);
4432
4433    /*
4434       last slice is zero-length and uncompressed; when we find it, we stop.
4435       We DON'T wait until there are no more slices; if we did that,
4436       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
4437     */
4438
4439    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
4440            MAX_STR_LEN - 1);
4441    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
4442
4443    log_msg(3, "file_to_openout = %s", file_to_openout);
4444    if (!(fout = fopen(file_to_openout, "w"))) {
4445        log_to_screen("Cannot openout outfile_fname - hard disk full?");
4446        return (1);
4447    }
4448    log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
4449
4450    for (sliceno = 1, finished = FALSE; !finished;) {
4451        if (!does_file_exist
4452            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
4453            &&
4454            !does_file_exist(slice_fname
4455                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
4456            &&
4457            !does_file_exist(slice_fname
4458                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
4459            &&
4460            !does_file_exist(slice_fname
4461                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
4462            log_msg(3,
4463                    "Cannot find a data slice or terminator slice on CD %d",
4464                    g_current_media_number);
4465            g_current_media_number++;
4466            sprintf(tmp,
4467                    "Asking for %s #%d so that I may read slice #%ld\n",
4468                    media_descriptor_string(bkpinfo->backup_media_type),
4469                    g_current_media_number, sliceno);
4470            log_msg(2, tmp);
4471            sprintf(tmp, "Restoring from %s #%d",
4472                    media_descriptor_string(bkpinfo->backup_media_type),
4473                    g_current_media_number);
4474            log_to_screen(tmp);
4475            insist_on_this_cd_number(g_current_media_number);
4476            log_to_screen("Continuing to restore.");
4477        } else {
4478            strcpy(tmp,
4479                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
4480            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
4481                log_msg(2,
4482                        "End of bigfile # %ld (slice %ld is the terminator)",
4483                        bigfileno + 1, sliceno);
4484                finished = TRUE;
4485                continue;
4486            } else {
4487                if (does_file_exist
4488                    (slice_fname
4489                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
4490                    strcpy(bzip2_command, "lzop");
4491                    strcpy(suffix, "lzo");
4492                } else
4493                    if (does_file_exist
4494                        (slice_fname
4495                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
4496                    strcpy(bzip2_command, "gzip");
4497                    strcpy(suffix, "gz");
4498                } else
4499                    if (does_file_exist
4500                        (slice_fname
4501                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
4502                    strcpy(bzip2_command, "bzip2");
4503                    strcpy(suffix, "bz2");
4504                } else
4505                    if (does_file_exist
4506                        (slice_fname
4507                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
4508                    strcpy(bzip2_command, "");
4509                    strcpy(suffix, "");
4510                } else {
4511                    log_to_screen("OK, that's pretty fsck0red...");
4512                    return (1);
4513                }
4514            }
4515            if (bzip2_command[0] != '\0') {
4516                sprintf(bzip2_command + strlen(bzip2_command),
4517                        " -dc %s 2>> %s",
4518                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
4519                                    suffix), MONDO_LOGFILE);
4520            } else {
4521                sprintf(bzip2_command, "cat %s 2>> %s",
4522                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
4523                                    suffix), MONDO_LOGFILE);
4524            }
4525            sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ",
4526                    media_descriptor_string(bkpinfo->backup_media_type),
4527                    g_current_media_number, bigfileno + 1, sliceno);
4528            log_msg(2, tmp);
4529
4530            if (!g_text_mode) {
4531                newtDrawRootText(0, g_noof_rows - 2, tmp);
4532                newtRefresh();
4533                strip_spaces(tmp);
4534                update_progress_form(tmp);
4535            }
4536            if (!(fbzip2 = popen(bzip2_command, "r"))) {
4537                fatal_error("Can't run popen command");
4538            }
4539            while (!feof(fbzip2)) {
4540                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
4541                if (siz > 0) {
4542                    sprintf(sz_msg, "Read %ld from fbzip2", siz);
4543                    siz = fwrite(bigblk, 1, siz, fout);
4544                    sprintf(sz_msg + strlen(sz_msg),
4545                            "; written %ld to fout", siz);
4546//        log_msg(2. sz_msg);
4547                }
4548            }
4549            paranoid_pclose(fbzip2);
4550
4551
4552            sliceno++;
4553            g_current_progress++;
4554        }
4555    }
4556/*
4557  memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
4558  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
4559  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
4560  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
4561  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
4562*/
4563    paranoid_fclose(fout);
4564    g_loglevel = old_loglevel;
4565
4566    if (use_ntfsprog_hack) {
4567        log_msg(3, "Waiting for ntfsclone to finish");
4568        sprintf(tmp,
4569                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
4570        while (system(tmp) == 0) {
4571            sleep(1);
4572        }
4573        log_it("OK, ntfsclone has really finished");
4574    }
4575
4576    if (strcmp(outfile_fname, "/dev/null")) {
4577        chown(outfile_fname, biggiestruct.properties.st_uid,
4578              biggiestruct.properties.st_gid);
4579        chmod(outfile_fname, biggiestruct.properties.st_mode);
4580        ubuf->actime = biggiestruct.properties.st_atime;
4581        ubuf->modtime = biggiestruct.properties.st_mtime;
4582        utime(outfile_fname, ubuf);
4583    }
4584    paranoid_free(bigblk);
4585    paranoid_free(checksum);
4586    paranoid_free(outfile_fname);
4587    paranoid_free(tmp);
4588    paranoid_free(bzip2_command);
4589    paranoid_free(ntfsprog_command);
4590    paranoid_free(suffix);
4591    paranoid_free(sz_devfile);
4592
4593    return (retval);
4594}
4595
4596/**************************************************************************
4597 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
4598 **************************************************************************/
4599
4600
4601
4602/**
4603 * Restore a biggiefile from the currently opened stream.
4604 * @param bkpinfo The backup information structure. Fields used:
4605 * - @c bkpinfo->restore_path
4606 * - @c bkpinfo->zip_exe
4607 * @param orig_bf_fname The original filename of the biggiefile.
4608 * @param biggiefile_number The number of the biggiefile (starting from 0).
4609 * @param orig_checksum Unused.
4610 * @param biggiefile_size Unused.
4611 * @param filelist The node structure containing the list of files to be restored.
4612 * If @p orig_bf_fname is not in the list, it will be ignored.
4613 * @return 0 for success (or skip), nonzero for failure.
4614 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
4615 */
4616int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
4617                                     long long biggiefile_size, //UNUSED
4618                                     struct s_node *filelist,
4619                                     int use_ntfsprog,
4620                                     char *pathname_of_last_file_restored)
4621{
4622    FILE *pout;
4623    FILE *fin;
4624
4625  /** mallocs ********/
4626    char *tmp;
4627    char *command;
4628    char *outfile_fname;
4629    char *ntfsprog_command;
4630    char *sz_devfile;
4631    char *ntfsprog_fifo;
4632    char *file_to_openout = NULL;
4633
4634    struct s_node *node;
4635
4636    int old_loglevel;
4637    long current_slice_number = 0;
4638    int retval = 0;
4639    int res = 0;
4640    int ctrl_chr = '\0';
4641    long long slice_siz;
4642    bool dummy_restore = FALSE;
4643    bool use_ntfsprog_hack = FALSE;
4644    pid_t pid;
4645    struct s_filename_and_lstat_info biggiestruct;
4646    struct utimbuf the_utime_buf, *ubuf;
4647    ubuf = &the_utime_buf;
4648
4649    malloc_string(tmp);
4650    malloc_string(ntfsprog_fifo);
4651    malloc_string(outfile_fname);
4652    malloc_string(command);
4653    malloc_string(sz_devfile);
4654    malloc_string(ntfsprog_command);
4655    old_loglevel = g_loglevel;
4656    assert(bkpinfo != NULL);
4657    assert(orig_bf_fname != NULL);
4658    assert(orig_checksum != NULL);
4659
4660    pathname_of_last_file_restored[0] = '\0';
4661    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
4662        use_ntfsprog = 1;
4663        log_msg(1, "%s --- pih=YES", orig_bf_fname);
4664    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
4665        use_ntfsprog = 0;
4666        log_msg(1, "%s --- pih=NO", orig_bf_fname);
4667    } else {
4668        use_ntfsprog = 0;
4669        log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
4670    }
4671
4672    strncpy(pathname_of_last_file_restored, orig_bf_fname,
4673            MAX_STR_LEN - 1);
4674    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
4675
4676    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
4677
4678    if (filelist != NULL) {
4679        node = find_string_at_node(filelist, orig_bf_fname);
4680        if (!node) {
4681            dummy_restore = TRUE;
4682            log_msg(1,
4683                    "Skipping big file %ld (%s) - not in biggielist subset",
4684                    biggiefile_number + 1, orig_bf_fname);
4685            pathname_of_last_file_restored[0] = '\0';
4686        } else if (!(node->selected)) {
4687            dummy_restore = TRUE;
4688            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
4689                    orig_bf_fname);
4690            pathname_of_last_file_restored[0] = '\0';
4691        }
4692    }
4693
4694    if (use_ntfsprog) {
4695        if (strncmp(orig_bf_fname, "/dev/", 5)) {
4696            log_msg(1,
4697                    "I was in error when I set use_ntfsprog to TRUE.");
4698            log_msg(1, "%s isn't even in /dev", orig_bf_fname);
4699            use_ntfsprog = FALSE;
4700        }
4701    }
4702
4703    if (use_ntfsprog) {
4704        g_loglevel = 4;
4705        strcpy(outfile_fname, orig_bf_fname);
4706        use_ntfsprog_hack = TRUE;
4707        log_msg(2,
4708                "Calling ntfsclone in background because %s is a /dev entry",
4709                outfile_fname);
4710        sprintf(sz_devfile, "%s/%d.%d.000", 
4711                bkpinfo->tmpdir,
4712                (int) (random() % 32768),
4713                (int) (random() % 32768));
4714        mkfifo(sz_devfile, 0x770);
4715        strcpy(ntfsprog_fifo, sz_devfile);
4716        file_to_openout = ntfsprog_fifo;
4717        switch (pid = fork()) {
4718        case -1:
4719            fatal_error("Fork failure");
4720        case 0:
4721            log_msg(3,
4722                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
4723                    outfile_fname, ntfsprog_fifo);
4724            res =
4725                feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
4726//          log_msg(3, "CHILD - fip - exiting");
4727            exit(res);
4728            break;
4729        default:
4730            log_msg(3,
4731                    "feed_into_ntfsprog() called in background --- pid=%ld",
4732                    (long int) (pid));
4733        }
4734    } else {
4735        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
4736        {
4737            strcpy(outfile_fname, orig_bf_fname);
4738        } else                  // biggiefile
4739        {
4740            sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
4741                    orig_bf_fname);
4742        }
4743        use_ntfsprog_hack = FALSE;
4744        ntfsprog_fifo[0] = '\0';
4745        file_to_openout = outfile_fname;
4746        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
4747        {
4748            make_hole_for_file(outfile_fname);
4749        }
4750        sprintf(tmp, "Reassembling big file %ld (%s)",
4751                biggiefile_number + 1, orig_bf_fname);
4752        log_msg(2, tmp);
4753    }
4754
4755    if (dummy_restore) {
4756        sprintf(outfile_fname, "/dev/null");
4757    }
4758
4759    if (!bkpinfo->zip_exe[0]) {
4760        sprintf(command, "cat > \"%s\"", file_to_openout);
4761    } else {
4762        sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
4763                file_to_openout, MONDO_LOGFILE);
4764        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
4765            /* Ignore SIGPIPE for gzip as it causes errors on big files
4766             * Cf: http://trac.mondorescue.org/ticket/244
4767             */
4768            signal(SIGPIPE,SIG_IGN);
4769        }
4770    }
4771    sprintf(tmp, "Pipe command = '%s'", command);
4772    log_msg(3, tmp);
4773
4774    /* restore biggiefile, one slice at a time */
4775    if (!(pout = popen(command, "w"))) {
4776        fatal_error("Cannot pipe out");
4777    }
4778    for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
4779         ctrl_chr != BLK_STOP_A_BIGGIE;
4780         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
4781        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
4782            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
4783        }
4784        sprintf(tmp, "Working on file #%ld, slice #%ld    ",
4785                biggiefile_number + 1, current_slice_number);
4786        log_msg(2, tmp);
4787        if (!g_text_mode) {
4788            newtDrawRootText(0, g_noof_rows - 2, tmp);
4789            newtRefresh();
4790        }
4791        strip_spaces(tmp);
4792        update_progress_form(tmp);
4793        if (current_slice_number == 0) {
4794            res =
4795                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
4796                                              slice_siz);
4797            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
4798                log_OS_error("blah blah");
4799            } else {
4800                if (fread
4801                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
4802                     fin) < sizeof(biggiestruct)) {
4803                    log_msg(2,
4804                            "Warning - unable to get biggiestruct of bigfile #%d",
4805                            biggiefile_number + 1);
4806                }
4807                paranoid_fclose(fin);
4808            }
4809        } else {
4810            res =
4811                read_file_from_stream_to_stream(pout, slice_siz);
4812        }
4813        retval += res;
4814        res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
4815        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
4816            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
4817        }
4818        current_slice_number++;
4819        g_current_progress++;
4820    }
4821    paranoid_pclose(pout);
4822
4823    if (bkpinfo->zip_exe[0]) {
4824        if (strcmp(bkpinfo->zip_exe, "gzip") == 0) {
4825            /* Re-enable SIGPIPE for gzip
4826             */
4827            signal(SIGPIPE, terminate_daemon);
4828        }
4829    }
4830
4831    log_msg(1, "pathname_of_last_file_restored is now %s",
4832            pathname_of_last_file_restored);
4833
4834    if (use_ntfsprog_hack) {
4835        log_msg(3, "Waiting for ntfsclone to finish");
4836        sprintf(tmp,
4837                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
4838        while (system(tmp) == 0) {
4839            sleep(1);
4840        }
4841        log_msg(3, "OK, ntfsclone has really finished");
4842    }
4843
4844    log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
4845    log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
4846    if (strcmp(outfile_fname, "/dev/null")) {
4847        chmod(outfile_fname, biggiestruct.properties.st_mode);
4848        chown(outfile_fname, biggiestruct.properties.st_uid,
4849              biggiestruct.properties.st_gid);
4850        ubuf->actime = biggiestruct.properties.st_atime;
4851        ubuf->modtime = biggiestruct.properties.st_mtime;
4852        utime(outfile_fname, ubuf);
4853    }
4854
4855    paranoid_free(tmp);
4856    paranoid_free(outfile_fname);
4857    paranoid_free(command);
4858    paranoid_free(ntfsprog_command);
4859    paranoid_free(sz_devfile);
4860    paranoid_free(ntfsprog_fifo);
4861    g_loglevel = old_loglevel;
4862    return (retval);
4863}
4864
4865/**************************************************************************
4866 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
4867 **************************************************************************/
4868
4869
4870
4871/**
4872 * Restore @p tarball_fname from CD.
4873 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
4874 * This will be used unmodified.
4875 * @param current_tarball_number The number (starting from 0) of the fileset
4876 * we're restoring now.
4877 * @param filelist The node structure containing the list of files to be
4878 * restored. If no file in the afioball is in this list, afio will still be
4879 * called, but nothing will be written.
4880 * @return 0 for success, nonzero for failure.
4881 */
4882int
4883restore_a_tarball_from_CD(char *tarball_fname,
4884                          long current_tarball_number,
4885                          struct s_node *filelist)
4886{
4887    int retval = 0;
4888    int res;
4889    char *p;
4890
4891  /** malloc **/
4892    char *command;
4893    char *tmp;
4894    char *filelist_name;
4895    char *filelist_subset_fname;
4896    char *executable;
4897    char *temp_log;
4898    char screen_message[100];
4899    long matches = 0;
4900    bool use_star;
4901    char *xattr_fname;
4902    char *acl_fname;
4903//  char files_to_restore_this_time_fname[MAX_STR_LEN];
4904
4905    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
4906    malloc_string(command);
4907    malloc_string(tmp);
4908    malloc_string(filelist_name);
4909    malloc_string(filelist_subset_fname);
4910    malloc_string(executable);
4911    malloc_string(temp_log);
4912    malloc_string(xattr_fname);
4913    malloc_string(acl_fname);
4914
4915    log_msg(5, "Entering");
4916    filelist_subset_fname[0] = '\0';
4917    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
4918//  sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
4919    sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
4920    run_program_and_log_output(command, 9);
4921    sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
4922            (int) (random() % 32768));
4923
4924    sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
4925            current_tarball_number);
4926    if (length_of_file(filelist_name) <= 2) {
4927        log_msg(2, "There are _zero_ files in filelist '%s'",
4928                filelist_name);
4929        log_msg(2,
4930                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
4931        log_msg(2,
4932                "but it's non-critical. It's cosmetic. Don't worry about it.");
4933        retval = 0;
4934        goto leave_sub;
4935    }
4936    if (count_lines_in_file(filelist_name) <= 0
4937        || length_of_file(tarball_fname) <= 0) {
4938        log_msg(3, "length_of_file(%s) = %llu", tarball_fname,
4939                length_of_file(tarball_fname));
4940        sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
4941                current_tarball_number);
4942        log_to_screen(tmp);
4943        retval = 1;
4944        goto leave_sub;
4945    }
4946
4947    if (filelist) {
4948        sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
4949                current_tarball_number);
4950        if ((matches =
4951             save_filelist_entries_in_common(filelist_name, filelist,
4952                                             filelist_subset_fname,
4953                                             use_star))
4954            <= 0) {
4955            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
4956            log_msg(1, tmp);
4957        } else {
4958            log_msg(3, "Saved fileset %ld's subset to %s",
4959                    current_tarball_number, filelist_subset_fname);
4960        }
4961        sprintf(screen_message, "Tarball #%ld --- %ld matches",
4962                current_tarball_number, matches);
4963        log_to_screen(screen_message);
4964    } else {
4965        filelist_subset_fname[0] = '\0';
4966    }
4967
4968    if (filelist == NULL || matches > 0) {
4969        if (g_getfattr) {
4970            sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
4971                MNT_CDROM "/archives", current_tarball_number);
4972        }
4973        if (g_getfacl) {
4974            sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
4975                current_tarball_number);
4976        }
4977        if (strstr(tarball_fname, ".bz2")) {
4978            strcpy(executable, "bzip2");
4979        } else if (strstr(tarball_fname, ".gz")) {
4980            strcpy(executable, "gzip");
4981        } else if (strstr(tarball_fname, ".lzo")) {
4982            strcpy(executable, "lzop");
4983        } else {
4984            executable[0] = '\0';
4985        }
4986        if (executable[0]) {
4987            sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
4988            if (run_program_and_log_output(tmp, FALSE)) {
4989                log_to_screen
4990                    ("(compare_a_tarball) Compression program not found - oh no!");
4991                paranoid_MR_finish(1);
4992            }
4993            strcpy(tmp, executable);
4994            sprintf(executable, "-P %s -Z", tmp);
4995        }
4996#ifdef __FreeBSD__
4997#define BUFSIZE 512
4998#else
4999#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
5000#endif
5001
5002//      if (strstr(tarball_fname, ".star."))
5003        if (use_star) {
5004            sprintf(command,
5005                    "star -x -force-remove -U " STAR_ACL_SZ
5006                    " errctl= file=%s", tarball_fname);
5007            if (strstr(tarball_fname, ".bz2")) {
5008                strcat(command, " -bz");
5009            }
5010        } else {
5011            if (filelist_subset_fname[0] != '\0') {
5012                sprintf(command,
5013                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
5014                        TAPE_BLOCK_SIZE,
5015                        BUFSIZE, executable, filelist_subset_fname,
5016//             files_to_restore_this_time_fname,
5017                        tarball_fname);
5018            } else {
5019                sprintf(command,
5020                        "afio -i -b %ld -c %ld -M 8m %s %s",
5021                        TAPE_BLOCK_SIZE,
5022                        BUFSIZE, executable, tarball_fname);
5023            }
5024        }
5025#undef BUFSIZE
5026        sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
5027                temp_log);
5028        log_msg(1, "command = '%s'", command);
5029        unlink(temp_log);
5030        res = system(command);
5031        if (res) {
5032            p = strstr(command, "-acl ");
5033            if (p) {
5034                p[0] = p[1] = p[2] = p[3] = ' ';
5035                log_msg(1, "new command = '%s'", command);
5036                res = system(command);
5037            }
5038        }
5039        if (res && length_of_file(temp_log) < 5) {
5040            res = 0;
5041        }
5042
5043        if (g_getfattr) {
5044            log_msg(1, "Setting fattr list %s", xattr_fname);
5045            if (length_of_file(xattr_fname) > 0) {
5046                res = set_fattr_list(filelist_subset_fname, xattr_fname);
5047                if (res) {
5048                    log_to_screen
5049                        ("Errors occurred while setting extended attributes");
5050                } else {
5051                    log_msg(1, "I set xattr OK");
5052                }
5053                retval += res;
5054            }
5055        }
5056        if (g_getfacl) {
5057            log_msg(1, "Setting acl list %s", acl_fname);
5058            if (length_of_file(acl_fname) > 0) {
5059                res = set_acl_list(filelist_subset_fname, acl_fname);
5060                if (res) {
5061                    log_to_screen
5062                        ("Errors occurred while setting access control lists");
5063                } else {
5064                    log_msg(1, "I set ACL OK");
5065                }
5066                retval += res;
5067            }
5068        }
5069        if (retval) {
5070            sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
5071            system(command);
5072            log_msg(2, "Errors occurred while processing fileset #%d",
5073                    current_tarball_number);
5074        } else {
5075            log_msg(2, "Fileset #%d processed OK", current_tarball_number);
5076        }
5077    }
5078    if (does_file_exist("/PAUSE")) {
5079        popup_and_OK
5080            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
5081    }
5082    unlink(filelist_subset_fname);
5083    unlink(xattr_fname);
5084    unlink(acl_fname);
5085    unlink(temp_log);
5086
5087  leave_sub:
5088    paranoid_free(command);
5089    paranoid_free(tmp);
5090    paranoid_free(filelist_name);
5091    paranoid_free(filelist_subset_fname);
5092    paranoid_free(executable);
5093    paranoid_free(temp_log);
5094    paranoid_free(xattr_fname);
5095    paranoid_free(acl_fname);
5096    log_msg(5, "Leaving");
5097    return (retval);
5098}
5099
5100/**************************************************************************
5101 *END_RESTORE_A_TARBALL_FROM_CD                                           *
5102 **************************************************************************/
5103
5104
5105/**
5106 * Restore a tarball from the currently opened stream.
5107 * @param bkpinfo The backup information structure. Fields used:
5108 * - @c bkpinfo->backup_media_type
5109 * - @c bkpinfo->media_device
5110 * - @c bkpinfo->zip_exe
5111 * @param tarball_fname The filename of the afioball to restore.
5112 * @param current_tarball_number The number (starting from 0) of the fileset
5113 * we're restoring now.
5114 * @param filelist The node structure containing the list of files to be
5115 * restored. If no file in the afioball is in this list, afio will still be
5116 * called, but nothing will be written.
5117 * @param size The size (in @b bytes) of the afioball.
5118 * @return 0 for success, nonzero for failure.
5119 */
5120int
5121restore_a_tarball_from_stream(char *tarball_fname,
5122                              long current_tarball_number,
5123                              struct s_node *filelist,
5124                              long long size, char *xattr_fname,
5125                              char *acl_fname)
5126{
5127    int retval = 0;
5128    int res = 0;
5129
5130  /** malloc add ***/
5131    char *tmp;
5132    char *command;
5133    char *afio_fname;
5134    char *filelist_fname;
5135    char *filelist_subset_fname;
5136    char *executable;
5137    long matches = 0;
5138    bool restore_this_fileset = FALSE;
5139    bool use_star;
5140
5141    assert(bkpinfo != NULL);
5142    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
5143    malloc_string(filelist_subset_fname);
5144    malloc_string(filelist_fname);
5145    malloc_string(afio_fname);
5146    malloc_string(executable);
5147    malloc_string(command);
5148    malloc_string(tmp);
5149    filelist_subset_fname[0] = '\0';
5150    /* to do it with a file... */
5151    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
5152    sprintf(tmp,
5153            "Restoring from fileset #%ld (%ld KB) on %s #%d",
5154            current_tarball_number, (long) size >> 10,
5155            media_descriptor_string(bkpinfo->backup_media_type),
5156            g_current_media_number);
5157    log_msg(2, tmp);
5158    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
5159
5160  /****************************************************************************
5161   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
5162   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
5163   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
5164   ****************************************************************************/
5165    filelist_fname[0] = filelist_subset_fname[0] = '\0';
5166    sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
5167            current_tarball_number);
5168    sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
5169            current_tarball_number);
5170    sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
5171            bkpinfo->tmpdir, current_tarball_number);
5172//  sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
5173    res = read_file_from_stream_to_file(afio_fname, size);
5174    if (strstr(tarball_fname, ".star")) {
5175        bkpinfo->use_star = TRUE;
5176    }
5177    if (res) {
5178        log_msg(1, "Warning - error reading afioball from tape");
5179    }
5180    if (bkpinfo->compression_level == 0) {
5181        executable[0] = '\0';
5182    } else {
5183        if (bkpinfo->use_star) {
5184            strcpy(executable, " -bz");
5185        } else {
5186            sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
5187        }
5188    }
5189
5190    if (!filelist)              // if unconditional restore then restore entire fileset
5191    {
5192        restore_this_fileset = TRUE;
5193    } else                      // If restoring selectively then get TOC from tarball
5194    {
5195        if (strstr(tarball_fname, ".star.")) {
5196            use_star = TRUE;
5197            sprintf(command, "star -t file=%s %s", afio_fname, executable);
5198        } else {
5199            use_star = FALSE;
5200            sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
5201                    executable, afio_fname);
5202        }
5203        sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
5204                MONDO_LOGFILE);
5205        log_msg(1, "command = %s", command);
5206        if (system(command)) {
5207            log_msg(4, "Warning - error occurred while retrieving TOC");
5208        }
5209        if ((matches =
5210             save_filelist_entries_in_common(filelist_fname, filelist,
5211                                             filelist_subset_fname,
5212                                             use_star))
5213            <= 0 || length_of_file(filelist_subset_fname) < 2) {
5214            if (length_of_file(filelist_subset_fname) < 2) {
5215                log_msg(1, "No matches found in fileset %ld",
5216                        current_tarball_number);
5217            }
5218            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
5219            log_msg(2, tmp);
5220            restore_this_fileset = FALSE;
5221        } else {
5222            log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
5223                    matches, current_tarball_number,
5224                    filelist_subset_fname);
5225            restore_this_fileset = TRUE;
5226        }
5227    }
5228
5229// Concoct the call to star/afio to restore files
5230    if (strstr(tarball_fname, ".star."))    // star
5231    {
5232        sprintf(command, "star -x file=%s %s", afio_fname, executable);
5233        if (filelist) {
5234            sprintf(command + strlen(command), " list=%s",
5235                    filelist_subset_fname);
5236        }
5237    } else                      // afio
5238    {
5239        sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
5240                executable);
5241        if (filelist) {
5242            sprintf(command + strlen(command), " -w %s",
5243                    filelist_subset_fname);
5244        }
5245        sprintf(command + strlen(command), " %s", afio_fname);
5246    }
5247    sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
5248
5249// Call if IF there are files to restore (selectively/unconditionally)
5250    if (restore_this_fileset) {
5251        log_msg(1, "Calling command='%s'", command);
5252        paranoid_system(command);
5253
5254        if (g_getfattr) {
5255            iamhere("Restoring xattr stuff");
5256            res = set_fattr_list(filelist_subset_fname, xattr_fname);
5257            if (res) {
5258                log_msg(1, "Errors occurred while setting xattr");
5259            } else {
5260                log_msg(1, "I set xattr OK");
5261            }
5262            retval += res;
5263        }
5264
5265        if (g_getfacl) {
5266            iamhere("Restoring acl stuff");
5267            res = set_acl_list(filelist_subset_fname, acl_fname);
5268            if (res) {
5269                log_msg(1, "Errors occurred while setting ACL");
5270            } else {
5271                log_msg(1, "I set ACL OK");
5272            }
5273            retval += res;
5274        }
5275
5276    } else {
5277        log_msg(1, "NOT CALLING '%s'", command);
5278    }
5279
5280    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
5281        log_to_screen("Paused after set %ld", current_tarball_number);
5282        popup_and_OK("Pausing. Press ENTER to continue.");
5283    }
5284
5285    unlink(filelist_subset_fname);
5286    unlink(filelist_fname);
5287    unlink(afio_fname);
5288
5289    paranoid_free(filelist_subset_fname);
5290    paranoid_free(filelist_fname);
5291    paranoid_free(afio_fname);
5292    paranoid_free(command);
5293    paranoid_free(tmp);
5294    return (retval);
5295}
5296
5297/**************************************************************************
5298 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
5299 **************************************************************************/
5300
5301
5302
5303
5304/**
5305 * Restore all biggiefiles from all media in this CD backup.
5306 * The CD with the last afioball should be currently mounted.
5307 * @param bkpinfo The backup information structure. @c backup_media_type is the
5308 * only field used in this function.
5309 * @param filelist The node structure containing the list of files to be
5310 * restored. If a prospective biggiefile is not in this list, it will be ignored.
5311 * @return 0 for success, nonzero for failure.
5312 */
5313int
5314restore_all_biggiefiles_from_CD(struct s_node *filelist)
5315{
5316    int retval = 0;
5317    int res = 0;
5318    long noof_biggiefiles, bigfileno = 0, total_slices;
5319  /** malloc **/
5320    char *tmp;
5321    bool just_changed_cds = FALSE;
5322    char *xattr_fname;
5323    char *acl_fname;
5324    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
5325    char *pathname_of_last_biggie_restored;
5326    FILE *fbw = NULL;
5327
5328    malloc_string(xattr_fname);
5329    malloc_string(acl_fname);
5330    malloc_string(tmp);
5331    malloc_string(biggies_whose_EXATs_we_should_set);
5332    malloc_string(pathname_of_last_biggie_restored);
5333    assert(bkpinfo != NULL);
5334
5335    sprintf(biggies_whose_EXATs_we_should_set,
5336            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
5337    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
5338        log_msg(1, "Warning - cannot openout %s",
5339                biggies_whose_EXATs_we_should_set);
5340    }
5341
5342    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
5343    total_slices = atol(tmp);
5344    sprintf(tmp, "Reassembling large files      ");
5345    mvaddstr_and_log_it(g_currentY, 0, tmp);
5346    if (length_of_file(BIGGIELIST) < 6) {
5347        log_msg(1, "OK, no biggielist; not restoring biggiefiles");
5348        return (0);
5349    }
5350    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
5351    if (noof_biggiefiles <= 0) {
5352        log_msg(2,
5353                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
5354        return (0);
5355    }
5356    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
5357            noof_biggiefiles);
5358    log_msg(2, tmp);
5359
5360    open_progress_form("Reassembling large files",
5361                       "I am now reassembling all the large files.",
5362                       "Please wait. This may take some time.",
5363                       "", total_slices);
5364    for (bigfileno = 0 ; bigfileno < noof_biggiefiles ;) {
5365        log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
5366        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
5367            log_msg(3,
5368                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
5369            log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
5370                    bigfileno + 1,
5371                    media_descriptor_string(bkpinfo->backup_media_type),
5372                    g_current_media_number);
5373            log_msg(3, "Slicename would have been %s",
5374                    slice_fname(bigfileno, 0, ARCHIVES_PATH, ""));
5375            // I'm not positive 'just_changed_cds' is even necessary...
5376            if (just_changed_cds) {
5377                just_changed_cds = FALSE;
5378                log_msg(3,
5379                        "I'll continue to scan this CD for bigfiles to be restored.");
5380            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
5381                insist_on_this_cd_number(++g_current_media_number);
5382                sprintf(tmp, "Restoring from %s #%d",
5383                        media_descriptor_string(bkpinfo->backup_media_type),
5384                        g_current_media_number);
5385                log_to_screen(tmp);
5386                just_changed_cds = TRUE;
5387            } else {
5388                /* That big file doesn't exist, but the followings may */
5389                /* So we need to continue looping */
5390                log_msg(2, "There was no bigfile #%ld. That's OK.",
5391                    bigfileno + 1);
5392                log_msg(2, "I'm going to stop restoring bigfiles now.");
5393                retval++;
5394                bigfileno++;
5395            }
5396        } else {
5397            just_changed_cds = FALSE;
5398            sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
5399            update_progress_form(tmp);
5400            res =
5401                restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
5402            iamhere(pathname_of_last_biggie_restored);
5403            if (fbw && pathname_of_last_biggie_restored[0]) {
5404                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
5405            }
5406            retval += res;
5407            bigfileno++;
5408
5409        }
5410    }
5411
5412    if (fbw) {
5413        fclose(fbw);
5414        if (g_getfattr) {
5415            sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
5416            if (length_of_file(xattr_fname) > 0) {
5417                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
5418            }
5419        }
5420        if (g_getfacl) {
5421            sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
5422            if (length_of_file(acl_fname) > 0) {
5423                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
5424            }
5425        }
5426    }
5427    if (does_file_exist("/PAUSE")) {
5428        popup_and_OK
5429            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
5430    }
5431    close_progress_form();
5432    if (retval) {
5433        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
5434    } else {
5435        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
5436    }
5437    paranoid_free(xattr_fname);
5438    paranoid_free(acl_fname);
5439    paranoid_free(tmp);
5440    paranoid_free(biggies_whose_EXATs_we_should_set);
5441    paranoid_free(pathname_of_last_biggie_restored);
5442    return (retval);
5443}
5444
5445/**************************************************************************
5446 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
5447 **************************************************************************/
5448
5449
5450
5451/**
5452 * Restore all afioballs from all CDs in the backup.
5453 * The first CD should be inserted (if not, it will be asked for).
5454 * @param bkpinfo The backup information structure. @c backup_media_type is the
5455 * only field used in @e this function.
5456 * @param filelist The node structure containing the list of files to be
5457 * restored. If no file in some particular afioball is in this list, afio will
5458 * still be called for that fileset, but nothing will be written.
5459 * @return 0 for success, or the number of filesets that failed.
5460 */
5461int
5462restore_all_tarballs_from_CD(struct s_node *filelist)
5463{
5464    int retval = 0;
5465    int res;
5466    int attempts;
5467    long current_tarball_number = 0;
5468    long max_val;
5469  /**malloc ***/
5470    char *tmp;
5471    char *tarball_fname;
5472    char *progress_str;
5473    char *comment;
5474
5475    malloc_string(tmp);
5476    malloc_string(tarball_fname);
5477    malloc_string(progress_str);
5478    malloc_string(comment);
5479
5480    assert(bkpinfo != NULL);
5481
5482    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
5483    log_msg(2,
5484            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
5485    if (g_current_media_number != 1) {
5486        log_msg(3, "OK, that's jacked up.");
5487        g_current_media_number = 1;
5488    }
5489    insist_on_this_cd_number(g_current_media_number);
5490    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
5491    max_val = atol(tmp) + 1;
5492    sprintf(progress_str, "Restoring from %s #%d",
5493            media_descriptor_string(bkpinfo->backup_media_type),
5494            g_current_media_number);
5495    log_to_screen(progress_str);
5496    open_progress_form("Restoring from archives",
5497                       "Restoring data from the archives.",
5498                       "Please wait. This may take some time.",
5499                       progress_str, max_val);
5500    for (;;) {
5501        insist_on_this_cd_number(g_current_media_number);
5502        update_progress_form(progress_str);
5503        sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
5504                current_tarball_number);
5505        if (!does_file_exist(tarball_fname)) {
5506            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
5507                current_tarball_number);
5508        }
5509        if (!does_file_exist(tarball_fname)) {
5510            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
5511                    current_tarball_number);
5512        }
5513        if (!does_file_exist(tarball_fname)) {
5514            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
5515                    current_tarball_number);
5516        }
5517        if (!does_file_exist(tarball_fname)) {
5518            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
5519                    current_tarball_number);
5520        }
5521        if (!does_file_exist(tarball_fname)) {
5522            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
5523                    current_tarball_number);
5524        }
5525        if (!does_file_exist(tarball_fname)) {
5526            if (current_tarball_number == 0) {
5527                log_to_screen
5528                    ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
5529                return (0);
5530            }
5531            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
5532                || system("find " MNT_CDROM
5533                          "/archives/slice* > /dev/null 2> /dev/null") ==
5534                0) {
5535                break;
5536            }
5537            g_current_media_number++;
5538            sprintf(progress_str, "Restoring from %s #%d",
5539                    media_descriptor_string(bkpinfo->backup_media_type),
5540                    g_current_media_number);
5541            log_to_screen(progress_str);
5542        } else {
5543            sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
5544                    current_tarball_number,
5545                    media_descriptor_string(bkpinfo->backup_media_type),
5546                    g_current_media_number);
5547//    log_msg(3, "progress_str = %s", progress_str);
5548            for (res = 999, attempts = 0; attempts < 3 && res != 0;
5549                 attempts++) {
5550                res =
5551                    restore_a_tarball_from_CD(tarball_fname,
5552                                              current_tarball_number,
5553                                              filelist);
5554            }
5555            sprintf(tmp, "%s #%d, fileset #%ld - restore ",
5556                    media_descriptor_string(bkpinfo->backup_media_type),
5557                    g_current_media_number, current_tarball_number);
5558            if (res) {
5559                strcat(tmp, "reported errors");
5560            } else if (attempts > 1) {
5561                strcat(tmp, "succeeded");
5562            } else {
5563                strcat(tmp, "succeeded");
5564            }
5565            if (attempts > 1) {
5566                sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
5567                        attempts);
5568            }
5569            strcpy(comment, tmp);
5570            if (attempts > 1) {
5571                log_to_screen(comment);
5572            }
5573
5574            retval += res;
5575            current_tarball_number++;
5576            g_current_progress++;
5577        }
5578    }
5579    close_progress_form();
5580    if (retval) {
5581        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
5582    } else {
5583        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
5584    }
5585    paranoid_free(tmp);
5586    paranoid_free(tarball_fname);
5587    paranoid_free(progress_str);
5588    paranoid_free(comment);
5589
5590    return (retval);
5591}
5592
5593/**************************************************************************
5594 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
5595 **************************************************************************/
5596
5597
5598
5599/**
5600 * Restore all biggiefiles from the currently opened stream.
5601 * @param bkpinfo The backup information structure. Passed to other functions.
5602 * @param filelist The node structure containing the list of files to be
5603 * restored. If a prospective biggiefile is not in the list, it will be ignored.
5604 * @return 0 for success, or the number of biggiefiles that failed.
5605 */
5606int
5607restore_all_biggiefiles_from_stream(struct s_node *filelist)
5608{
5609    long noof_biggiefiles;
5610    long current_bigfile_number = 0;
5611    long total_slices;
5612
5613    int retval = 0;
5614    int res = 0;
5615    int ctrl_chr;
5616
5617  /** malloc add ****/
5618    char *tmp;
5619    char *biggie_fname;
5620    char *biggie_cksum;
5621    char *xattr_fname;
5622    char *acl_fname;
5623    char *p;
5624    char *pathname_of_last_biggie_restored;
5625    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
5626    long long biggie_size;
5627    FILE *fbw = NULL;
5628
5629    malloc_string(tmp);
5630    malloc_string(biggie_fname);
5631    malloc_string(biggie_cksum);
5632    malloc_string(xattr_fname);
5633    malloc_string(acl_fname);
5634    malloc_string(biggies_whose_EXATs_we_should_set);
5635    malloc_string(pathname_of_last_biggie_restored);
5636    assert(bkpinfo != NULL);
5637
5638    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
5639
5640    total_slices = atol(tmp);
5641    sprintf(tmp, "Reassembling large files      ");
5642    if (g_getfattr) {
5643        sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
5644    }
5645    if (g_getfacl) {
5646        sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
5647    }
5648    mvaddstr_and_log_it(g_currentY, 0, tmp);
5649    sprintf(biggies_whose_EXATs_we_should_set,
5650            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
5651    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
5652        log_msg(1, "Warning - cannot openout %s",
5653                biggies_whose_EXATs_we_should_set);
5654    }
5655// get xattr and acl files if they're there
5656    res =
5657        read_header_block_from_stream(&biggie_size, biggie_fname,
5658                                      &ctrl_chr);
5659    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
5660        res =
5661            read_EXAT_files_from_tape(&biggie_size, biggie_fname,
5662                                      &ctrl_chr, xattr_fname, acl_fname);
5663    }
5664
5665    noof_biggiefiles = atol(biggie_fname);
5666    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
5667            noof_biggiefiles);
5668    log_msg(2, tmp);
5669    open_progress_form("Reassembling large files",
5670                       "I am now reassembling all the large files.",
5671                       "Please wait. This may take some time.",
5672                       "", total_slices);
5673
5674    for (res =
5675         read_header_block_from_stream(&biggie_size, biggie_fname,
5676                                       &ctrl_chr);
5677         ctrl_chr != BLK_STOP_BIGGIEFILES;
5678         res =
5679         read_header_block_from_stream(&biggie_size, biggie_fname,
5680                                       &ctrl_chr)) {
5681        if (ctrl_chr != BLK_START_A_NORMBIGGIE
5682            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
5683            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
5684        }
5685        p = strrchr(biggie_fname, '/');
5686        if (!p) {
5687            p = biggie_fname;
5688        } else {
5689            p++;
5690        }
5691        sprintf(tmp, "Restoring big file %ld (%lld K)",
5692                current_bigfile_number + 1, biggie_size / 1024);
5693        update_progress_form(tmp);
5694        res = restore_a_biggiefile_from_stream(biggie_fname,
5695                                               current_bigfile_number,
5696                                               biggie_cksum,
5697                                               biggie_size,
5698                                               filelist, ctrl_chr,
5699                                               pathname_of_last_biggie_restored);
5700        log_msg(1, "I believe I have restored %s",
5701                pathname_of_last_biggie_restored);
5702        if (fbw && pathname_of_last_biggie_restored[0]) {
5703            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
5704        }
5705        retval += res;
5706        current_bigfile_number++;
5707
5708    }
5709    if (current_bigfile_number != noof_biggiefiles
5710        && noof_biggiefiles != 0) {
5711        sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
5712                current_bigfile_number, noof_biggiefiles);
5713    } else {
5714        sprintf(tmp,
5715                "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
5716                noof_biggiefiles, current_bigfile_number);
5717    }
5718    log_msg(1, tmp);
5719
5720    if (fbw) {
5721        fclose(fbw);
5722        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
5723            iamhere("Setting biggie-EXATs");
5724            if (g_getfattr) {
5725                if (length_of_file(xattr_fname) > 0) {
5726                    log_msg(1, "set_fattr_List(%s,%s)",
5727                        biggies_whose_EXATs_we_should_set, xattr_fname);
5728                    set_fattr_list(biggies_whose_EXATs_we_should_set,
5729                               xattr_fname);
5730                }
5731            }
5732            if (g_getfacl) {
5733                if (length_of_file(acl_fname) > 0) {
5734                    log_msg(1, "set_acl_list(%s,%s)",
5735                            biggies_whose_EXATs_we_should_set, acl_fname);
5736                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
5737                }
5738            }
5739        } else {
5740            iamhere
5741                ("No biggiefiles selected. So, no biggie-EXATs to set.");
5742        }
5743    }
5744    if (does_file_exist("/PAUSE")) {
5745        popup_and_OK
5746            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
5747    }
5748
5749    close_progress_form();
5750    if (retval) {
5751        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
5752    } else {
5753        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
5754    }
5755    paranoid_free(biggies_whose_EXATs_we_should_set);
5756    paranoid_free(pathname_of_last_biggie_restored);
5757    paranoid_free(biggie_fname);
5758    paranoid_free(biggie_cksum);
5759    paranoid_free(xattr_fname);
5760    paranoid_free(acl_fname);
5761    paranoid_free(tmp);
5762    return (retval);
5763}
5764
5765/**************************************************************************
5766 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
5767 **************************************************************************/
5768
5769
5770
5771
5772
5773
5774/**
5775 * Restore all afioballs from the currently opened tape stream.
5776 * @param bkpinfo The backup information structure. Fields used:
5777 * - @c bkpinfo->backup_media_type
5778 * - @c bkpinfo->restore_path
5779 * @param filelist The node structure containing the list of files to be
5780 * restored. If no file in an afioball is in this list, afio will still be
5781 * called for that fileset, but nothing will be written.
5782 * @return 0 for success, or the number of filesets that failed.
5783 */
5784int
5785restore_all_tarballs_from_stream(struct s_node *filelist)
5786{
5787    int retval = 0;
5788    int res;
5789    long current_afioball_number = 0;
5790    int ctrl_chr;
5791    long max_val /*, total_noof_files */ ;
5792
5793  /** malloc **/
5794    char *tmp;
5795    char *progress_str;
5796    char *tmp_fname;
5797    char *xattr_fname;
5798    char *acl_fname;
5799
5800    long long tmp_size;
5801
5802    malloc_string(tmp);
5803    malloc_string(progress_str);
5804    malloc_string(tmp_fname);
5805    assert(bkpinfo != NULL);
5806    malloc_string(xattr_fname);
5807    malloc_string(acl_fname);
5808    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
5809    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
5810    max_val = atol(tmp) + 1;
5811
5812    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
5813
5814    run_program_and_log_output("pwd", 5);
5815
5816    sprintf(progress_str, "Restoring from media #%d",
5817            g_current_media_number);
5818    log_to_screen(progress_str);
5819    open_progress_form("Restoring from archives",
5820                       "Restoring data from the archives.",
5821                       "Please wait. This may take some time.",
5822                       progress_str, max_val);
5823
5824    log_msg(3, "hey");
5825
5826    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
5827    if (res) {
5828        log_msg(2, "Warning - error reading afioball from tape");
5829    }
5830    retval += res;
5831    if (ctrl_chr != BLK_START_AFIOBALLS) {
5832        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
5833    }
5834    log_msg(2, "ho");
5835    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
5836    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
5837        update_progress_form(progress_str);
5838        if (g_getfattr) {
5839            sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
5840                current_afioball_number);
5841            unlink(xattr_fname);
5842        }
5843        if (g_getfacl) {
5844            sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
5845                current_afioball_number);
5846            unlink(acl_fname);
5847        }
5848        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
5849            iamhere("Reading EXAT files from tape");
5850            res =
5851                read_EXAT_files_from_tape(&tmp_size, tmp_fname,
5852                                          &ctrl_chr, xattr_fname,
5853                                          acl_fname);
5854        }
5855        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
5856            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
5857        }
5858        sprintf(tmp,
5859                "Restoring from fileset #%ld (name=%s, size=%ld K)",
5860                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
5861        res =
5862            restore_a_tarball_from_stream(tmp_fname,
5863                                          current_afioball_number,
5864                                          filelist, tmp_size, xattr_fname,
5865                                          acl_fname);
5866        retval += res;
5867        if (res) {
5868            sprintf(tmp, "Fileset %ld - errors occurred",
5869                    current_afioball_number);
5870            log_to_screen(tmp);
5871        }
5872        res =
5873            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
5874        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
5875            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
5876        }
5877
5878        current_afioball_number++;
5879        g_current_progress++;
5880        sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
5881                current_afioball_number,
5882                media_descriptor_string(bkpinfo->backup_media_type),
5883                g_current_media_number);
5884        res =
5885            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
5886        if (g_getfattr) {
5887            unlink(xattr_fname);
5888        }
5889        if (g_getfacl) {
5890            unlink(acl_fname);
5891        }
5892    }                           // next
5893    log_msg(1, "All done with afioballs");
5894    close_progress_form();
5895    if (retval) {
5896        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
5897    } else {
5898        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
5899    }
5900    paranoid_free(tmp);
5901    paranoid_free(progress_str);
5902    paranoid_free(tmp_fname);
5903    paranoid_free(xattr_fname);
5904    paranoid_free(acl_fname);
5905    return (retval);
5906}
5907
5908/**************************************************************************
5909 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
5910 **************************************************************************/
5911
5912/* @} - end of LLrestoreGroup */
5913
5914
5915/**
5916 * Restore all files in @p filelist.
5917 * @param bkpinfo The backup information structure. Most fields are used.
5918 * @param filelist The node structure containing the list of files to be
5919 * restored.
5920 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
5921 * @ingroup restoreGroup
5922 */
5923int restore_everything(struct s_node *filelist)
5924{
5925    int resA;
5926    int resB;
5927
5928  /** mallco ***/
5929    char *cwd;
5930    char *newpath;
5931    char *tmp;
5932    assert(bkpinfo != NULL);
5933
5934    malloc_string(cwd);
5935    malloc_string(newpath);
5936    malloc_string(tmp);
5937    log_msg(2, "restore_everything() --- starting");
5938    g_current_media_number = 1;
5939    getcwd(cwd, MAX_STR_LEN - 1);
5940    sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
5941    run_program_and_log_output(tmp, FALSE);
5942    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
5943    chdir(bkpinfo->restore_path);
5944    getcwd(newpath, MAX_STR_LEN - 1);
5945    log_msg(1, "path is now %s", newpath);
5946    log_msg(1, "restoring everything");
5947    if (!find_home_of_exe("petris") && !g_text_mode) {
5948        newtDrawRootText(0, g_noof_rows - 2,
5949                         "Press ALT-<left cursor> twice to play Petris :-) ");
5950        newtRefresh();
5951    }
5952    mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
5953    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
5954        mount_media();
5955        mvaddstr_and_log_it(g_currentY++, 0,
5956                            "Restoring OS and data from streaming media");
5957        if (bkpinfo->backup_media_type == cdstream) {
5958            openin_cdstream();
5959        } else {
5960            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
5961            openin_tape();
5962        }
5963        resA = restore_all_tarballs_from_stream(filelist);
5964        resB = restore_all_biggiefiles_from_stream(filelist);
5965        if (bkpinfo->backup_media_type == cdstream) {
5966            closein_cdstream();
5967        } else {
5968            closein_tape();
5969        }
5970    } else {
5971        mvaddstr_and_log_it(g_currentY++, 0,
5972                            "Restoring OS and data from CD/USB   ");
5973        mount_media();
5974        resA = restore_all_tarballs_from_CD(filelist);
5975        resB = restore_all_biggiefiles_from_CD(filelist);
5976    }
5977    chdir(cwd);
5978    if (resA + resB) {
5979        log_to_screen("Errors occurred while data was being restored.");
5980    }
5981    if (length_of_file("/etc/raidtab") > 0) {
5982        log_msg(2, "Copying local raidtab to restored filesystem");
5983        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
5984                                   "/etc/raidtab", FALSE);
5985    }
5986    kill_petris();
5987    log_msg(2, "restore_everything() --- leaving");
5988    paranoid_free(cwd);
5989    paranoid_free(newpath);
5990    paranoid_free(tmp);
5991    return (resA + resB);
5992}
5993
5994/**************************************************************************
5995 *END_RESTORE_EVERYTHING                                                  *
5996 **************************************************************************/
5997
5998
5999
6000/**
6001 * @brief Haha. You wish! (This function is not implemented :-)
6002 */
6003int
6004restore_live_from_monitas_server(char *monitas_device,
6005                                 char *restore_this_directory,
6006                                 char *restore_here)
6007     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
6008{
6009    FILE *fout;
6010    int retval = 0;
6011    int i;
6012    int j;
6013    struct mountlist_itself the_mountlist;
6014    static struct raidlist_itself the_raidlist;
6015  /** malloc **/
6016    char tmp[MAX_STR_LEN + 1];
6017    char command[MAX_STR_LEN + 1];
6018    char datablock[256 * 1024];
6019    char datadisks_fname[MAX_STR_LEN + 1];
6020    long k;
6021    long length;
6022    long long llt;
6023    struct s_node *filelist = NULL;
6024    assert(bkpinfo != NULL);
6025    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
6026    assert(restore_this_directory != NULL);
6027    assert(restore_here != NULL);
6028
6029    sprintf(tmp, "restore_here = '%s'", restore_here);
6030
6031    log_msg(2, tmp);
6032
6033    log_msg(2, "restore_live_from_monitas_server() - starting");
6034    unlink("/tmp/mountlist.txt");
6035    unlink("/tmp/filelist.full");
6036    unlink("/tmp/biggielist.txt");
6037    if (restore_here[0] == '\0') {
6038        strcpy(bkpinfo->restore_path, MNT_RESTORING);
6039    } else {
6040        strcpy(bkpinfo->restore_path, restore_here);
6041    }
6042    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
6043    sprintf(tmp, "FYI - data will be restored to %s",
6044            bkpinfo->restore_path);
6045    log_msg(3, tmp);
6046    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
6047    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
6048            (int) (random() % 32768));
6049    chdir(bkpinfo->tmpdir);
6050
6051    sprintf(command, "cat %s", monitas_device);
6052    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
6053    if (!(fout = fopen(datadisks_fname, "w"))) {
6054        log_OS_error(datadisks_fname);
6055        return (1);
6056    }
6057    for (i = 0; i < 32; i++) {
6058        for (j = 0; j < 4; j++) {
6059            for (length = k = 0; length < 256 * 1024; length += k) {
6060                k = fread(datablock + length, 1, 256 * 1024 - length,
6061                          g_tape_stream);
6062            }
6063            fwrite(datablock, 1, length, fout);
6064            g_tape_posK += length;
6065        }
6066    }
6067    paranoid_fclose(fout);
6068    sprintf(command,
6069            "tar -zxvf %s ./tmp/mondo-restore.cfg ./tmp/mountlist.txt ./tmp/filelist.full ./tmp/biggielist.txt",
6070            datadisks_fname);
6071    run_program_and_log_output(command, 4);
6072    read_header_block_from_stream(&llt, tmp, &i);
6073    read_header_block_from_stream(&llt, tmp, &i);
6074
6075    unlink(datadisks_fname);
6076    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
6077    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
6078
6079
6080    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
6081    iamhere("FIXME");
6082    fatal_error("This will fail");
6083    sprintf(command,
6084            "grep -E '^%s.*$' %s > %s",
6085            restore_this_directory, g_filelist_full, g_filelist_full);
6086    if (system(command)) {
6087        retval++;
6088        log_to_screen
6089            ("Error(s) occurred while processing filelist and wildcard");
6090    }
6091    iamhere("FIXME");
6092    fatal_error("This will fail");
6093    sprintf(command,
6094            "grep -E '^%s.*$' %s > %s",
6095            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
6096    if (system(command)) {
6097        log_msg(1,
6098                "Error(s) occurred while processing biggielist and wildcard");
6099    }
6100    sprintf(command, "touch %s", g_biggielist_txt);
6101    run_program_and_log_output(command, FALSE);
6102//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
6103    retval += restore_everything(filelist);
6104    free_filelist(filelist);
6105    log_msg(2, "--------End of restore_live_from_monitas_server--------");
6106    return (retval);
6107}
6108
6109/**************************************************************************
6110 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
6111 **************************************************************************/
6112
6113
6114
6115
6116extern void wait_until_software_raids_are_prepped(char *, int);
6117
6118
6119char which_restore_mode(void);
6120
6121
6122/**
6123 * Log a "don't panic" message to the logfile.
6124 */
6125void welcome_to_mondorestore()
6126{
6127    log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
6128    log_msg(0,
6129            "DON'T PANIC! Mondorestore logs almost everything, so please ");
6130    log_msg(0,
6131            "don't break out in a cold sweat just because you see a few  ");
6132    log_msg(0,
6133            "error messages in the log. Read them; analyze them; see if  ");
6134    log_msg(0,
6135            "they are significant; above all, verify your backups! Please");
6136    log_msg(0,
6137            "attach a compressed copy of this log to any e-mail you send ");
6138    log_msg(0,
6139            "to the Mondo mailing list when you are seeking technical    ");
6140    log_msg(0,
6141            "support. Without it, we can't help you.            - DevTeam");
6142    log_msg(0,
6143            "------------------------------------------------------------");
6144    log_msg(0,
6145            "BTW, despite (or perhaps because of) the wealth of messages,");
6146    log_msg(0,
6147            "some users are inclined to stop reading this log.  If Mondo ");
6148    log_msg(0,
6149            "stopped for some reason, chances are it's detailed here.    ");
6150    log_msg(0,
6151            "More than likely there's a message at the very end of this  ");
6152    log_msg(0,
6153            "log that will tell you what is wrong.  Please read it!      ");
6154    log_msg(0,
6155            "------------------------------------------------------------");
6156}
6157
6158
6159
6160/**
6161 * Restore the user's data.
6162 * What did you think it did, anyway? :-)
6163 */
6164int main(int argc, char *argv[])
6165{
6166    FILE *fin;
6167    FILE *fout;
6168    int retval = 0;
6169    int res;
6170//  int c;
6171    char *tmp;
6172
6173    struct mountlist_itself *mountlist;
6174    struct raidlist_itself *raidlist;
6175    struct s_node *filelist;
6176    char *a, *b;
6177    bool run_postnuke = FALSE;
6178
6179  /**************************************************************************
6180   * hugo-                                                                  *
6181   * busy stuff here - it needs some comments -stan                           *
6182   *                                                                        *
6183   **************************************************************************/
6184    if (getuid() != 0) {
6185        fprintf(stderr, "Please run as root.\r\n");
6186        exit(127);
6187    }
6188    if (!
6189        (bkpinfo = malloc(sizeof(struct s_bkpinfo)))) {
6190