source: branches/2.2.6/mondo/src/mondorestore/mondorestore.c @ 1930

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

Renaming of files to be in conformity with stable and ease aplication of patches between branches.

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