source: branches/2.2.5/mondo/src/mondorestore/mondo-restore.c @ 1881

Last change on this file since 1881 was 1881, checked in by bruno, 11 years ago

Should fix the problem with the prefix always asked at restore time, even when it's not NFS

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