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

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

Solve an issue on Bigfiles:
When one bigfile (such as mondo's ISO image) is deleted during the archiving,
it creates a hole in the suite of Bigfiles (in my case bigfile 0 was missing)
So at restore time, it was aborting the rest of the restoration of big files as this one was failing, which is worng
Now mondorestore loops until it reaches the number of bigfiles, so will restore the others.

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