source: branches/2.2.2/mondo/src/mondorestore/mondo-restore.c @ 1315

Last change on this file since 1315 was 1315, checked in by bruno, 13 years ago

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt? is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

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