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

Last change on this file since 1316 was 1316, checked in by Bruno Cornec, 13 years ago

MONDO_LOGFILE is rather a char* exported by each main program (consolidation of those mecanisms in .h files with ps_*)

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