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

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

Render bkpinfo global (potential issue on thread, but should not be a problem as that structure is indeed static during archive)
Should solve the tmpdir issue from previous rev.
May still not compile

  • Property svn:keywords set to Id
File size: 100.5 KB
Line 
1/***************************************************************************
2$Id: mondo-restore.c 1645 2007-09-24 01:04:43Z 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 1645 2007-09-24 01:04:43Z bruno $";
37
38/**************************************************************************
39 * Globals                                                                *
40 **************************************************************************/
41extern char *g_tmpfs_mountpt;   // declared in libmondo-tools.c
42extern struct s_bkpinfo *g_bkpinfo_DONTUSETHIS; // used by finish() to free
43                                                // up global bkpinfo struct
44extern bool g_text_mode;
45extern FILE *g_fprep;
46extern double g_kernel_version;
47extern int g_partition_table_locked_up;
48extern int g_noof_rows;
49
50extern int partition_everything(struct mountlist_itself *mountlist);
51
52
53/**
54 * @name Restore-Time Globals
55 * @ingroup globalGroup
56 * @{
57 */
58/**
59 * If TRUE, then SIGPIPE was just caught.
60 * Set by the signal handler; cleared after it's handled.
61 */
62bool g_sigpipe_caught = FALSE;
63
64/**
65 * If TRUE, then we're restoring from ISOs or an NFS server.
66 * If FALSE, then we're restoring from some kind of real media (tape, CD, etc.)
67 */
68bool g_ISO_restore_mode = FALSE;    /* are we in Iso Mode? */
69
70/**
71 * If TRUE, then we have had a successful "nuke" restore.
72 */
73bool g_I_have_just_nuked = FALSE;
74
75/**
76 * The device to mount to get at the ISO images. Ignored unless @p g_ISO_restore_mode.
77 */
78char *g_isodir_device;
79
80/**
81 * The format of @p g_isodir_device. Ignored unless @p g_ISO_restore_mode.
82 */
83char *g_isodir_format;
84
85/**
86 * The location of 'biggielist.txt', containing the biggiefiles on the current archive set.
87 */
88char *g_biggielist_txt;
89
90/**
91 * The location of 'filelist.full', containing all files (<em>including biggiefiles</em>) on
92 * the current archive set.
93 */
94char *g_filelist_full;
95
96/**
97 * The location of a file containing a list of the devices that were archived
98 * as images, not as individual files.
99 */
100char *g_filelist_imagedevs;
101
102/**
103 * The location of a file containing a list of imagedevs to actually restore.
104 * @see g_filelist_imagedevs
105 */
106char *g_imagedevs_restthese;
107
108/**
109 * The location of 'mondo-restore.cfg', containing the metadata
110 * information for this backup.
111 */
112char *g_mondo_cfg_file;
113
114/**
115 * The location of 'mountlist.txt', containing the information on the
116 * user's partitions and hard drives.
117 */
118char *g_mountlist_fname;
119
120/**
121 * Mondo's home directory during backup. Unused in mondorestore; included
122 * to avoid link errors.
123 */
124char *g_mondo_home;
125
126extern char *g_getfacl;
127extern char *g_getfattr;
128
129/* @} - end of "Restore-Time Globals" in globalGroup */
130
131
132
133extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
134                                 char direction);
135
136
137
138/**************************************************************************
139 * COMPAQ PROLIANT Stuff:  needs some special help                        *
140**************************************************************************/
141
142/**
143 * The message to display if we detect that the user is using a Compaq Proliant.
144 */
145#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."
146
147
148
149
150/**
151 * Allow the user to modify the mountlist before we partition & format their drives.
152 * @param bkpinfo The backup information structure. @c disaster_recovery is the only field used.
153 * @param mountlist The mountlist to let the user modify.
154 * @param raidlist The raidlist that goes with @p mountlist.
155 * @return 0 for success, nonzero for failure.
156 * @ingroup restoreGuiGroup
157 */
158int let_user_edit_the_mountlist(struct mountlist_itself *mountlist,
159                                struct raidlist_itself *raidlist)
160{
161    int retval = 0, res = 0;
162
163    log_msg(2, "let_user_edit_the_mountlist() --- starting");
164
165    assert(bkpinfo != NULL);
166    assert(mountlist != NULL);
167    assert(raidlist != NULL);
168    if (!bkpinfo->disaster_recovery) {
169        strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
170        log_msg(2, "I guess you're testing edit_mountlist()");
171    }
172    if (!does_file_exist(g_mountlist_fname)) {
173        log_to_screen(g_mountlist_fname);
174        log_to_screen("does not exist");
175        return (1);
176    }
177
178    retval = load_mountlist(mountlist, g_mountlist_fname);
179    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
180    if (retval) {
181        log_to_screen
182            ("Warning - load_raidtab_into_raidlist returned an error");
183    }
184    res = edit_mountlist(g_mountlist_fname, mountlist, raidlist);
185    if (res) {
186        return (1);
187    }
188
189    save_mountlist_to_disk(mountlist, g_mountlist_fname);
190    save_raidlist_to_raidtab(raidlist, RAIDTAB_FNAME);
191
192    log_to_screen("I have finished editing the mountlist for you.");
193
194    return (retval);
195}
196
197
198
199
200
201/**
202 * Determine whether @p mountlist contains a Compaq diagnostic partition.
203 * @param mountlist The mountlist to examine.
204 * @return TRUE if there's a Compaq diagnostic partition; FALSE if not.
205 * @ingroup restoreUtilityGroup
206 */
207bool
208partition_table_contains_Compaq_diagnostic_partition(struct
209                                                     mountlist_itself *
210                                                     mountlist)
211{
212    int i;
213
214    assert(mountlist != NULL);
215
216    for (i = 0; i < mountlist->entries; i++) {
217        if (strstr(mountlist->el[i].format, "ompaq")) {
218            log_msg(2, "mountlist[%d] (%s) is %s (Compaq alert!)",
219                    i, mountlist->el[i].device, mountlist->el[i].format);
220
221            return (TRUE);
222        }
223    }
224    return (FALSE);
225}
226
227/**************************************************************************
228 *END_PARTITION_TABLE_CONTAINS_COMPAQ_DIAGNOSTIC_PARTITION                *
229 **************************************************************************/
230
231
232/**
233 * Allow the user to abort the backup if we find that there is a Compaq diagnostic partition.
234 * @note This function does not actually check for the presence of a Compaq partition.
235 * @ingroup restoreUtilityGroup
236 */
237void offer_to_abort_because_Compaq_Proliants_suck(void)
238{
239    popup_and_OK(COMPAQ_PROLIANTS_SUCK);
240    if (ask_me_yes_or_no
241        ("Would you like to reboot and use your Compaq CD to prep your hard drive?"))
242    {
243        fatal_error
244            ("Aborting. Please reboot and prep your hard drive with your Compaq CD.");
245    }
246}
247
248/**************************************************************************
249 *END_OFFER_TO_ABORT_BECAUSE_COMPAQ_PROLIANTS_SUCK                        *
250 **************************************************************************/
251
252
253
254/**
255 * Call interactive_mode(), nuke_mode(), or compare_mode() depending on the user's choice.
256 * @param bkpinfo The backup information structure. Most fields are used.
257 * @param mountlist The mountlist containing information about the user's partitions.
258 * @param raidlist The raidlist to go with @p mountlist.
259 * @return The return code from the mode function called.
260 * @ingroup restoreGroup
261 */
262int
263catchall_mode(struct mountlist_itself *mountlist,
264              struct raidlist_itself *raidlist)
265{
266    char c, *tmp;
267    int retval = 0;
268
269    iamhere("inside catchall");
270    assert(bkpinfo != NULL);
271    assert(mountlist != NULL);
272    assert(raidlist != NULL);
273    malloc_string(tmp);
274    iamhere("pre wrm");
275    c = which_restore_mode();
276    iamhere("post wrm");
277    if (c == 'I' || c == 'N' || c == 'C') {
278        interactively_obtain_media_parameters_from_user(FALSE);
279    } else {
280        popup_and_OK("No restoring or comparing will take place today.");
281        if (is_this_device_mounted("/mnt/cdrom")) {
282            run_program_and_log_output("umount /mnt/cdrom", FALSE);
283        }
284        if (g_ISO_restore_mode) {
285            sprintf(tmp, "umount %s", bkpinfo->isodir);
286            run_program_and_log_output(tmp, FALSE);
287        }
288        paranoid_MR_finish(0);
289    }
290
291    iamhere("post int");
292
293    if (bkpinfo->backup_media_type == iso) {
294        if (iso_fiddly_bits(bkpinfo, (c == 'N') ? TRUE : FALSE)) {
295            log_msg(2,
296                    "catchall_mode --- iso_fiddly_bits returned w/ error");
297            return (1);
298        } else {
299            log_msg(2, "catchall_mode --- iso_fiddly_bits ok");
300        }
301    }
302
303    if (c == 'I') {
304        log_msg(2, "IM selected");
305        retval += interactive_mode(mountlist, raidlist);
306    } else if (c == 'N') {
307        log_msg(2, "NM selected");
308        retval += nuke_mode(mountlist, raidlist);
309    } else if (c == 'C') {
310        log_msg(2, "CM selected");
311        retval += compare_mode(mountlist, raidlist);
312    }
313    paranoid_free(tmp);
314    return (retval);
315}
316
317/**************************************************************************
318 *END_CATCHALL_MODE                                                      *
319 **************************************************************************/
320
321/**************************************************************************
322 *END_  EXTRACT_CONFIG_FILE_FROM_RAMDISK                                  *
323 **************************************************************************/
324
325
326/**
327 * Locate an executable in the directory structure rooted at @p restg.
328 * @param out_path Where to put the executable.
329 * @param fname The basename of the executable.
330 * @param restg The directory structure to look in.
331 * @note If it could not be found in @p restg then @p fname is put in @p out_path.
332 * @ingroup restoreUtilityGroup
333 */
334void
335find_pathname_of_executable_preferably_in_RESTORING(char *out_path,
336                                                    char *fname,
337                                                    char *restg)
338{
339    assert(out_path != NULL);
340    assert_string_is_neither_NULL_nor_zerolength(fname);
341
342    sprintf(out_path, "%s/sbin/%s", restg, fname);
343    if (does_file_exist(out_path)) {
344        sprintf(out_path, "%s/usr/sbin/%s", restg, fname);
345        if (does_file_exist(out_path)) {
346            sprintf(out_path, "%s/bin/%s", restg, fname);
347            if (does_file_exist(out_path)) {
348                sprintf(out_path, "%s/usr/bin/%s", restg, fname);
349                if (does_file_exist(out_path)) {
350                    strcpy(out_path, fname);
351                }
352            }
353        }
354    }
355}
356
357/**************************************************************************
358 *END_FIND_PATHNAME_OF_EXECUTABLE_PREFERABLY_IN_RESTORING                 *
359 **************************************************************************/
360
361static void clean_blkid() {
362
363    char *tmp1 = NULL;
364
365    /* Clean up blkid cache file if they exist */
366    asprintf(&tmp1,"%s/etc/blkid.tab",bkpinfo->restore_path);
367    (void)unlink(tmp1);
368    paranoid_free(tmp1);
369    asprintf(&tmp1,"%s/etc/blkid.tab.old",bkpinfo->restore_path);
370    (void)unlink(tmp1);
371    paranoid_free(tmp1);
372}
373
374
375
376
377/**
378 * @addtogroup restoreGroup
379 * @{
380 */
381/**
382 * Restore the user's data, in a disaster recovery situation, prompting the
383 * user about whether or not to do every step.
384 * The user can edit the mountlist, choose files to restore, etc.
385 * @param bkpinfo The backup information structure. Most fields are used.
386 * @param mountlist The mountlist containing information about the user's partitions.
387 * @param raidlist The raidlist to go with @p mountlist.
388 * @return 0 for success, or the number of errors encountered.
389 */
390int
391interactive_mode(struct mountlist_itself *mountlist,
392                 struct raidlist_itself *raidlist)
393{
394    int retval = 0;
395    int res;
396    int ptn_errs = 0;
397    int fmt_errs = 0;
398
399    bool done;
400    bool restore_all;
401
402  /** needs malloc **********/
403    char *tmp;
404    char *fstab_fname;
405    char *old_restpath;
406
407    struct s_node *filelist;
408
409    /* try to partition and format */
410
411    log_msg(2, "interactive_mode --- starting (great, assertions OK)");
412
413    malloc_string(tmp);
414    malloc_string(fstab_fname);
415    malloc_string(old_restpath);
416    assert(bkpinfo != NULL);
417    assert(mountlist != NULL);
418    assert(raidlist != NULL);
419
420    log_msg(2, "interactive_mode --- assertions OK");
421
422    if (g_text_mode) {
423        if (!ask_me_yes_or_no
424            ("Interactive Mode + textonly = experimental! Proceed anyway?"))
425        {
426            fatal_error("Wise move.");
427        }
428    }
429
430    iamhere("About to load config file");
431    get_cfg_file_from_archive_or_bust();
432    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
433    iamhere("Done loading config file; resizing ML");
434    strcpy(tmp, bkpinfo->prefix);
435    if (popup_and_get_string
436        ("Prefix", "Prefix of your ISO images ?", tmp, MAX_STR_LEN / 4)) {
437        strcpy(bkpinfo->prefix, tmp);
438        log_msg(1, "Prefix set to %s",bkpinfo->prefix);
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"))    // Bruno's thing
869    {
870        log_to_screen
871            ("PC was restored successfully. Thank you for using Mondo Rescue.");
872        log_to_screen
873            ("Please visit our website at http://www.mondorescue.org for more information.");
874    } else {
875        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.");
876            popup_and_OK(tmp);
877        log_to_screen
878          ("Mondo has restored your system. Please wait for the command prompt.");
879        log_to_screen
880            ("Then remove the backup media and reboot.");
881        log_to_screen
882            ("Please visit our website at http://www.mondorescue.org for more information.");
883    }
884    g_I_have_just_nuked = TRUE;
885/*
886  if (!boot_loader_installed && !does_file_exist(DO_MBR_PLEASE))
887    {
888      log_to_screen("PLEASE RUN 'mondorestore --mbr' NOW TO INITIALIZE YOUR BOOT SECTOR");
889      write_one_liner_data_file(DO_MBR_PLEASE, "mondorestore --mbr");
890    }
891*/
892    return (retval);
893}
894
895/**************************************************************************
896 *END_NUKE_MODE                                                           *
897 **************************************************************************/
898
899
900
901/**
902 * Restore the user's data (or a subset of it) to the live filesystem.
903 * This should not be called if we're booted from CD!
904 * @param bkpinfo The backup information structure. Most fields are used.
905 * @return 0 for success, or the number of errors encountered.
906 */
907int restore_to_live_filesystem()
908{
909    int retval = 0;
910
911  /** malloc **/
912    char *old_restpath;
913
914    struct mountlist_itself *mountlist;
915//  static
916    struct raidlist_itself *raidlist;
917    struct s_node *filelist;
918
919    log_msg(1, "restore_to_live_filesystem() - starting");
920    assert(bkpinfo != NULL);
921    malloc_string(old_restpath);
922    mountlist = malloc(sizeof(struct mountlist_itself));
923    raidlist = malloc(sizeof(struct raidlist_itself));
924    if (!mountlist || !raidlist) {
925        fatal_error("Cannot malloc() mountlist and/or raidlist");
926    }
927
928    strcpy(bkpinfo->restore_path, "/");
929    if (!g_restoring_live_from_cd) {
930        popup_and_OK
931            ("Please insert tape/CD/boot floppy, then hit 'OK' to continue.");
932        sleep(1);
933    }
934    interactively_obtain_media_parameters_from_user(FALSE);
935    log_msg(2, "bkpinfo->media_device = %s", bkpinfo->media_device);
936    if (!bkpinfo->media_device[0]) {
937        log_msg(2, "Warning - failed to find media dev");
938    }
939
940
941    log_msg(2, "bkpinfo->isodir = %s", bkpinfo->isodir);
942
943    open_evalcall_form("Thinking...");
944
945    get_cfg_file_from_archive_or_bust();
946    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
947    load_mountlist(mountlist, g_mountlist_fname);   // in case read_cfg_file_into_bkpinfo
948
949    close_evalcall_form();
950    retval = load_mountlist(mountlist, g_mountlist_fname);
951    load_raidtab_into_raidlist(raidlist, RAIDTAB_FNAME);
952    filelist = process_filelist_and_biggielist();
953    if (filelist) {
954        save_filelist(filelist, "/tmp/selected-files.txt");
955        strcpy(old_restpath, bkpinfo->restore_path);
956        if (popup_and_get_string("Restore path",
957                                 "Restore files to where? )",
958                                 bkpinfo->restore_path, MAX_STR_LEN / 4)) {
959            iamhere("Restoring everything");
960            retval += restore_everything(filelist);
961            free_filelist(filelist);
962            strcpy(bkpinfo->restore_path, old_restpath);
963        } else {
964            free_filelist(filelist);
965        }
966        strcpy(bkpinfo->restore_path, old_restpath);
967    }
968    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
969        log_msg(2,
970                "Tape : I don't need to unmount or eject the CD-ROM.");
971    } else {
972        run_program_and_log_output("umount " MNT_CDROM, FALSE);
973        if (!bkpinfo->please_dont_eject) {
974            eject_device(bkpinfo->media_device);
975        }
976    }
977    run_program_and_log_output("umount " MNT_CDROM, FALSE);
978    if (!bkpinfo->please_dont_eject) {
979        eject_device(bkpinfo->media_device);
980    }
981    paranoid_free(old_restpath);
982    free(mountlist);
983    free(raidlist);
984    return (retval);
985}
986
987/**************************************************************************
988 *END_RESTORE_TO_LIVE_FILESYSTEM                                          *
989 **************************************************************************/
990
991/* @} - end of restoreGroup */
992
993
994#include <utime.h>
995/**
996 * @addtogroup LLrestoreGroup
997 * @{
998 */
999/**
1000 * Restore biggiefile @p bigfileno from the currently mounted CD.
1001 * @param bkpinfo The backup information structure. Fields used:
1002 * - @c bkpinfo->backup_media_type
1003 * - @c bkpinfo->restore_path
1004 * @param bigfileno The biggiefile number (starting from 0) to restore.
1005 * @param filelist The node structure containing the list of files to restore.
1006 * If the biggiefile is not in this list, it will be skipped (return value will
1007 * still indicate success).
1008 * @return 0 for success (or skip), nonzero for failure.
1009 */
1010int
1011restore_a_biggiefile_from_CD(long bigfileno,
1012                             struct s_node *filelist,
1013                             char *pathname_of_last_file_restored)
1014{
1015    FILE *fin;
1016    FILE *fout;
1017    FILE *fbzip2;
1018
1019  /** malloc ***/
1020    char *checksum, *outfile_fname, *tmp, *bzip2_command,
1021        *ntfsprog_command, *suffix, *sz_devfile;
1022    char *bigblk;
1023    char *p;
1024    int retval = 0;
1025    int finished = FALSE;
1026    long sliceno;
1027    long siz;
1028    char ntfsprog_fifo[MAX_STR_LEN];
1029    char *file_to_openout = NULL;
1030    struct s_filename_and_lstat_info biggiestruct;
1031    struct utimbuf the_utime_buf, *ubuf;
1032    bool use_ntfsprog_hack = FALSE;
1033    pid_t pid;
1034    int res = 0;
1035    int old_loglevel;
1036    char sz_msg[MAX_STR_LEN];
1037    struct s_node *node;
1038
1039    old_loglevel = g_loglevel;
1040    ubuf = &the_utime_buf;
1041    assert(bkpinfo != NULL);
1042
1043    malloc_string(checksum);
1044    malloc_string(outfile_fname);
1045    malloc_string(tmp);
1046    malloc_string(bzip2_command);
1047    malloc_string(ntfsprog_command);
1048    malloc_string(suffix);
1049    malloc_string(sz_devfile);
1050
1051    pathname_of_last_file_restored[0] = '\0';
1052    if (!(bigblk = malloc(TAPE_BLOCK_SIZE))) {
1053        fatal_error("Cannot malloc bigblk");
1054    }
1055
1056    if (!(fin = fopen(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""), "r"))) {
1057        log_to_screen("Cannot even open bigfile's info file");
1058        return (1);
1059    }
1060
1061    memset((void *) &biggiestruct, 0, sizeof(biggiestruct));
1062    if (fread((void *) &biggiestruct, 1, sizeof(biggiestruct), fin) <
1063        sizeof(biggiestruct)) {
1064        log_msg(2, "Warning - unable to get biggiestruct of bigfile #%d",
1065                bigfileno + 1);
1066    }
1067    paranoid_fclose(fin);
1068
1069    strcpy(checksum, biggiestruct.checksum);
1070
1071    if (!checksum[0]) {
1072        sprintf(tmp, "Warning - bigfile %ld does not have a checksum",
1073                bigfileno + 1);
1074        log_msg(3, tmp);
1075        p = checksum;
1076    }
1077
1078    if (!strncmp(biggiestruct.filename, "/dev/", 5))    // Whether NTFS or not :)
1079    {
1080        strcpy(outfile_fname, biggiestruct.filename);
1081    } else {
1082        sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1083                biggiestruct.filename);
1084    }
1085
1086    /* skip file if we have a selective restore subset & it doesn't match */
1087    if (filelist != NULL) {
1088        node = find_string_at_node(filelist, biggiestruct.filename);
1089        if (!node) {
1090            log_msg(0, "Skipping %s (name isn't in filelist)",
1091                    biggiestruct.filename);
1092            pathname_of_last_file_restored[0] = '\0';
1093            return (0);
1094        } else if (!(node->selected)) {
1095            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1096                    biggiestruct.filename);
1097            pathname_of_last_file_restored[0] = '\0';
1098            return (0);
1099        }
1100    }
1101    /* otherwise, continue */
1102
1103    log_msg(1, "DEFINITELY restoring %s", biggiestruct.filename);
1104    if (biggiestruct.use_ntfsprog) {
1105        if (strncmp(biggiestruct.filename, "/dev/", 5)) {
1106            log_msg(1,
1107                    "I was in error when I set biggiestruct.use_ntfsprog to TRUE.");
1108            log_msg(1, "%s isn't even in /dev", biggiestruct.filename);
1109            biggiestruct.use_ntfsprog = FALSE;
1110        }
1111    }
1112
1113    if (biggiestruct.use_ntfsprog)  // if it's an NTFS device
1114//  if (!strncmp ( biggiestruct.filename, "/dev/", 5))
1115    {
1116        g_loglevel = 4;
1117        use_ntfsprog_hack = TRUE;
1118        log_msg(2,
1119                "Calling ntfsclone in background because %s is an NTFS /dev entry",
1120                outfile_fname);
1121        sprintf(sz_devfile, "/tmp/%d.%d.000", (int) (random() % 32768),
1122                (int) (random() % 32768));
1123        mkfifo(sz_devfile, 0x770);
1124        strcpy(ntfsprog_fifo, sz_devfile);
1125        file_to_openout = ntfsprog_fifo;
1126        switch (pid = fork()) {
1127        case -1:
1128            fatal_error("Fork failure");
1129        case 0:
1130            log_msg(3,
1131                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1132                    biggiestruct.filename, ntfsprog_fifo);
1133            res =
1134                feed_outfrom_ntfsprog(biggiestruct.filename,
1135                                       ntfsprog_fifo);
1136//          log_msg(3, "CHILD - fip - exiting");
1137            exit(res);
1138            break;
1139        default:
1140            log_msg(3,
1141                    "feed_into_ntfsprog() called in background --- pid=%ld",
1142                    (long int) (pid));
1143        }
1144    } else {
1145        use_ntfsprog_hack = FALSE;
1146        ntfsprog_fifo[0] = '\0';
1147        file_to_openout = outfile_fname;
1148        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1149        {
1150            make_hole_for_file(outfile_fname);
1151        }
1152    }
1153
1154    sprintf(tmp, "Reassembling big file %ld (%s)", bigfileno + 1,
1155            outfile_fname);
1156    log_msg(2, tmp);
1157
1158    /*
1159       last slice is zero-length and uncompressed; when we find it, we stop.
1160       We DON'T wait until there are no more slices; if we did that,
1161       We might stop at end of CD, not at last slice (which is 0-len and uncompd)
1162     */
1163
1164    strncpy(pathname_of_last_file_restored, biggiestruct.filename,
1165            MAX_STR_LEN - 1);
1166    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1167
1168    log_msg(3, "file_to_openout = %s", file_to_openout);
1169    if (!(fout = fopen(file_to_openout, "w"))) {
1170        log_to_screen("Cannot openout outfile_fname - hard disk full?");
1171        return (1);
1172    }
1173    log_msg(3, "Opened out to %s", outfile_fname);  // CD/DVD --> mondorestore --> ntfsclone --> hard disk itself
1174
1175    for (sliceno = 1, finished = FALSE; !finished;) {
1176        if (!does_file_exist
1177            (slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""))
1178            &&
1179            !does_file_exist(slice_fname
1180                             (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))
1181            &&
1182            !does_file_exist(slice_fname
1183                             (bigfileno, sliceno, ARCHIVES_PATH, "gz"))
1184            &&
1185            !does_file_exist(slice_fname
1186                             (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1187            log_msg(3,
1188                    "Cannot find a data slice or terminator slice on CD %d",
1189                    g_current_media_number);
1190            g_current_media_number++;
1191            sprintf(tmp,
1192                    "Asking for %s #%d so that I may read slice #%ld\n",
1193                    media_descriptor_string(bkpinfo->backup_media_type),
1194                    g_current_media_number, sliceno);
1195            log_msg(2, tmp);
1196            sprintf(tmp, "Restoring from %s #%d",
1197                    media_descriptor_string(bkpinfo->backup_media_type),
1198                    g_current_media_number);
1199            log_to_screen(tmp);
1200            insist_on_this_cd_number(g_current_media_number);
1201            log_to_screen("Continuing to restore.");
1202        } else {
1203            strcpy(tmp,
1204                   slice_fname(bigfileno, sliceno, ARCHIVES_PATH, ""));
1205            if (does_file_exist(tmp) && length_of_file(tmp) == 0) {
1206                log_msg(2,
1207                        "End of bigfile # %ld (slice %ld is the terminator)",
1208                        bigfileno + 1, sliceno);
1209                finished = TRUE;
1210                continue;
1211            } else {
1212                if (does_file_exist
1213                    (slice_fname
1214                     (bigfileno, sliceno, ARCHIVES_PATH, "lzo"))) {
1215                    strcpy(bzip2_command, "lzop");
1216                    strcpy(suffix, "lzo");
1217                } else
1218                    if (does_file_exist
1219                        (slice_fname
1220                         (bigfileno, sliceno, ARCHIVES_PATH, "gz"))) {
1221                    strcpy(bzip2_command, "gzip");
1222                    strcpy(suffix, "gz");
1223                } else
1224                    if (does_file_exist
1225                        (slice_fname
1226                         (bigfileno, sliceno, ARCHIVES_PATH, "bz2"))) {
1227                    strcpy(bzip2_command, "bzip2");
1228                    strcpy(suffix, "bz2");
1229                } else
1230                    if (does_file_exist
1231                        (slice_fname
1232                         (bigfileno, sliceno, ARCHIVES_PATH, ""))) {
1233                    strcpy(bzip2_command, "");
1234                    strcpy(suffix, "");
1235                } else {
1236                    log_to_screen("OK, that's pretty fsck0red...");
1237                    return (1);
1238                }
1239            }
1240            if (bzip2_command[0] != '\0') {
1241                sprintf(bzip2_command + strlen(bzip2_command),
1242                        " -dc %s 2>> %s",
1243                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1244                                    suffix), MONDO_LOGFILE);
1245            } else {
1246                sprintf(bzip2_command, "cat %s 2>> %s",
1247                        slice_fname(bigfileno, sliceno, ARCHIVES_PATH,
1248                                    suffix), MONDO_LOGFILE);
1249            }
1250            sprintf(tmp, "Working on %s #%d, file #%ld, slice #%ld    ",
1251                    media_descriptor_string(bkpinfo->backup_media_type),
1252                    g_current_media_number, bigfileno + 1, sliceno);
1253            log_msg(2, tmp);
1254
1255            if (!g_text_mode) {
1256                newtDrawRootText(0, g_noof_rows - 2, tmp);
1257                newtRefresh();
1258                strip_spaces(tmp);
1259                update_progress_form(tmp);
1260            }
1261            if (!(fbzip2 = popen(bzip2_command, "r"))) {
1262                fatal_error("Can't run popen command");
1263            }
1264            while (!feof(fbzip2)) {
1265                siz = fread(bigblk, 1, TAPE_BLOCK_SIZE, fbzip2);
1266                if (siz > 0) {
1267                    sprintf(sz_msg, "Read %ld from fbzip2", siz);
1268                    siz = fwrite(bigblk, 1, siz, fout);
1269                    sprintf(sz_msg + strlen(sz_msg),
1270                            "; written %ld to fout", siz);
1271//        log_msg(2. sz_msg);
1272                }
1273            }
1274            paranoid_pclose(fbzip2);
1275
1276
1277            sliceno++;
1278            g_current_progress++;
1279        }
1280    }
1281/*
1282  memset(bigblk, TAPE_BLOCK_SIZE, 1); // This all looks very fishy...
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  fwrite( bigblk, 1, TAPE_BLOCK_SIZE, fout);
1287*/
1288    paranoid_fclose(fout);
1289    g_loglevel = old_loglevel;
1290
1291    if (use_ntfsprog_hack) {
1292        log_msg(3, "Waiting for ntfsclone to finish");
1293        sprintf(tmp,
1294                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1295        while (system(tmp) == 0) {
1296            sleep(1);
1297        }
1298        log_it("OK, ntfsclone has really finished");
1299    }
1300
1301    if (strcmp(outfile_fname, "/dev/null")) {
1302        chown(outfile_fname, biggiestruct.properties.st_uid,
1303              biggiestruct.properties.st_gid);
1304        chmod(outfile_fname, biggiestruct.properties.st_mode);
1305        ubuf->actime = biggiestruct.properties.st_atime;
1306        ubuf->modtime = biggiestruct.properties.st_mtime;
1307        utime(outfile_fname, ubuf);
1308    }
1309    paranoid_free(bigblk);
1310    paranoid_free(checksum);
1311    paranoid_free(outfile_fname);
1312    paranoid_free(tmp);
1313    paranoid_free(bzip2_command);
1314    paranoid_free(ntfsprog_command);
1315    paranoid_free(suffix);
1316    paranoid_free(sz_devfile);
1317
1318    return (retval);
1319}
1320
1321/**************************************************************************
1322 *END_ RESTORE_A_BIGGIEFILE_FROM_CD                                       *
1323 **************************************************************************/
1324
1325
1326
1327/**
1328 * Restore a biggiefile from the currently opened stream.
1329 * @param bkpinfo The backup information structure. Fields used:
1330 * - @c bkpinfo->restore_path
1331 * - @c bkpinfo->zip_exe
1332 * @param orig_bf_fname The original filename of the biggiefile.
1333 * @param biggiefile_number The number of the biggiefile (starting from 0).
1334 * @param orig_checksum Unused.
1335 * @param biggiefile_size Unused.
1336 * @param filelist The node structure containing the list of files to be restored.
1337 * If @p orig_bf_fname is not in the list, it will be ignored.
1338 * @return 0 for success (or skip), nonzero for failure.
1339 * @bug orig_checksum and biggiefile_size are unused (except to check that they are non-NULL).
1340 */
1341int restore_a_biggiefile_from_stream(char *orig_bf_fname, long biggiefile_number, char *orig_checksum,  //UNUSED
1342                                     long long biggiefile_size, //UNUSED
1343                                     struct s_node *filelist,
1344                                     int use_ntfsprog,
1345                                     char *pathname_of_last_file_restored)
1346{
1347    FILE *pout;
1348    FILE *fin;
1349
1350  /** mallocs ********/
1351    char *tmp;
1352    char *command;
1353    char *outfile_fname;
1354    char *ntfsprog_command;
1355    char *sz_devfile;
1356    char *ntfsprog_fifo;
1357    char *file_to_openout = NULL;
1358
1359    struct s_node *node;
1360
1361    int old_loglevel;
1362    long current_slice_number = 0;
1363    int retval = 0;
1364    int res = 0;
1365    int ctrl_chr = '\0';
1366    long long slice_siz;
1367    bool dummy_restore = FALSE;
1368    bool use_ntfsprog_hack = FALSE;
1369    pid_t pid;
1370    struct s_filename_and_lstat_info biggiestruct;
1371    struct utimbuf the_utime_buf, *ubuf;
1372    ubuf = &the_utime_buf;
1373
1374    malloc_string(tmp);
1375    malloc_string(ntfsprog_fifo);
1376    malloc_string(outfile_fname);
1377    malloc_string(command);
1378    malloc_string(sz_devfile);
1379    malloc_string(ntfsprog_command);
1380    old_loglevel = g_loglevel;
1381    assert(bkpinfo != NULL);
1382    assert(orig_bf_fname != NULL);
1383    assert(orig_checksum != NULL);
1384
1385    pathname_of_last_file_restored[0] = '\0';
1386    if (use_ntfsprog == BLK_START_A_PIHBIGGIE) {
1387        use_ntfsprog = 1;
1388        log_msg(1, "%s --- pih=YES", orig_bf_fname);
1389    } else if (use_ntfsprog == BLK_START_A_NORMBIGGIE) {
1390        use_ntfsprog = 0;
1391        log_msg(1, "%s --- pih=NO", orig_bf_fname);
1392    } else {
1393        use_ntfsprog = 0;
1394        log_msg(1, "%s --- pih=NO (weird marker though)", orig_bf_fname);
1395    }
1396
1397    strncpy(pathname_of_last_file_restored, orig_bf_fname,
1398            MAX_STR_LEN - 1);
1399    pathname_of_last_file_restored[MAX_STR_LEN - 1] = '\0';
1400
1401    /* open out to biggiefile to be restored (or /dev/null if biggiefile is not to be restored) */
1402
1403    if (filelist != NULL) {
1404        node = find_string_at_node(filelist, orig_bf_fname);
1405        if (!node) {
1406            dummy_restore = TRUE;
1407            log_msg(1,
1408                    "Skipping big file %ld (%s) - not in biggielist subset",
1409                    biggiefile_number + 1, orig_bf_fname);
1410            pathname_of_last_file_restored[0] = '\0';
1411        } else if (!(node->selected)) {
1412            dummy_restore = TRUE;
1413            log_msg(1, "Skipping %s (name isn't in biggielist subset)",
1414                    orig_bf_fname);
1415            pathname_of_last_file_restored[0] = '\0';
1416        }
1417    }
1418
1419    if (use_ntfsprog) {
1420        if (strncmp(orig_bf_fname, "/dev/", 5)) {
1421            log_msg(1,
1422                    "I was in error when I set use_ntfsprog to TRUE.");
1423            log_msg(1, "%s isn't even in /dev", orig_bf_fname);
1424            use_ntfsprog = FALSE;
1425        }
1426    }
1427
1428    if (use_ntfsprog) {
1429        g_loglevel = 4;
1430        strcpy(outfile_fname, orig_bf_fname);
1431        use_ntfsprog_hack = TRUE;
1432        log_msg(2,
1433                "Calling ntfsclone in background because %s is a /dev entry",
1434                outfile_fname);
1435        sprintf(sz_devfile, "%s/%d.%d.000", 
1436                bkpinfo->tmpdir,
1437                (int) (random() % 32768),
1438                (int) (random() % 32768));
1439        mkfifo(sz_devfile, 0x770);
1440        strcpy(ntfsprog_fifo, sz_devfile);
1441        file_to_openout = ntfsprog_fifo;
1442        switch (pid = fork()) {
1443        case -1:
1444            fatal_error("Fork failure");
1445        case 0:
1446            log_msg(3,
1447                    "CHILD - fip - calling feed_outfrom_ntfsprog(%s, %s)",
1448                    outfile_fname, ntfsprog_fifo);
1449            res =
1450                feed_outfrom_ntfsprog(outfile_fname, ntfsprog_fifo);
1451//          log_msg(3, "CHILD - fip - exiting");
1452            exit(res);
1453            break;
1454        default:
1455            log_msg(3,
1456                    "feed_into_ntfsprog() called in background --- pid=%ld",
1457                    (long int) (pid));
1458        }
1459    } else {
1460        if (!strncmp(orig_bf_fname, "/dev/", 5))    // non-NTFS partition
1461        {
1462            strcpy(outfile_fname, orig_bf_fname);
1463        } else                  // biggiefile
1464        {
1465            sprintf(outfile_fname, "%s/%s", bkpinfo->restore_path,
1466                    orig_bf_fname);
1467        }
1468        use_ntfsprog_hack = FALSE;
1469        ntfsprog_fifo[0] = '\0';
1470        file_to_openout = outfile_fname;
1471        if (!does_file_exist(outfile_fname))    // yes, it looks weird with the '!' but it's correct that way
1472        {
1473            make_hole_for_file(outfile_fname);
1474        }
1475        sprintf(tmp, "Reassembling big file %ld (%s)",
1476                biggiefile_number + 1, orig_bf_fname);
1477        log_msg(2, tmp);
1478    }
1479
1480    if (dummy_restore) {
1481        sprintf(outfile_fname, "/dev/null");
1482    }
1483
1484    if (!bkpinfo->zip_exe[0]) {
1485        sprintf(command, "cat > \"%s\"", file_to_openout);
1486    } else {
1487        sprintf(command, "%s -dc > \"%s\" 2>> %s", bkpinfo->zip_exe,
1488                file_to_openout, MONDO_LOGFILE);
1489    }
1490    sprintf(tmp, "Pipe command = '%s'", command);
1491    log_msg(3, tmp);
1492
1493    /* restore biggiefile, one slice at a time */
1494    if (!(pout = popen(command, "w"))) {
1495        fatal_error("Cannot pipe out");
1496    }
1497    for (res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1498         ctrl_chr != BLK_STOP_A_BIGGIE;
1499         res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr)) {
1500        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
1501            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
1502        }
1503        sprintf(tmp, "Working on file #%ld, slice #%ld    ",
1504                biggiefile_number + 1, current_slice_number);
1505        log_msg(2, tmp);
1506        if (!g_text_mode) {
1507            newtDrawRootText(0, g_noof_rows - 2, tmp);
1508            newtRefresh();
1509        }
1510        strip_spaces(tmp);
1511        update_progress_form(tmp);
1512        if (current_slice_number == 0) {
1513            res =
1514                read_file_from_stream_to_file("/tmp/biggie-blah.txt",
1515                                              slice_siz);
1516            if (!(fin = fopen("/tmp/biggie-blah.txt", "r"))) {
1517                log_OS_error("blah blah");
1518            } else {
1519                if (fread
1520                    ((void *) &biggiestruct, 1, sizeof(biggiestruct),
1521                     fin) < sizeof(biggiestruct)) {
1522                    log_msg(2,
1523                            "Warning - unable to get biggiestruct of bigfile #%d",
1524                            biggiefile_number + 1);
1525                }
1526                paranoid_fclose(fin);
1527            }
1528        } else {
1529            res =
1530                read_file_from_stream_to_stream(pout, slice_siz);
1531        }
1532        retval += res;
1533        res = read_header_block_from_stream(&slice_siz, tmp, &ctrl_chr);
1534        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
1535            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
1536        }
1537        current_slice_number++;
1538        g_current_progress++;
1539    }
1540    paranoid_pclose(pout);
1541
1542    log_msg(1, "pathname_of_last_file_restored is now %s",
1543            pathname_of_last_file_restored);
1544
1545    if (use_ntfsprog_hack) {
1546        log_msg(3, "Waiting for ntfsclone to finish");
1547        sprintf(tmp,
1548                " ps | grep \" ntfsclone \" | grep -v grep > /dev/null 2> /dev/null");
1549        while (system(tmp) == 0) {
1550            sleep(1);
1551        }
1552        log_msg(3, "OK, ntfsclone has really finished");
1553    }
1554
1555    log_msg(3, "biggiestruct.filename = %s", biggiestruct.filename);
1556    log_msg(3, "biggiestruct.checksum = %s", biggiestruct.checksum);
1557    if (strcmp(outfile_fname, "/dev/null")) {
1558        chmod(outfile_fname, biggiestruct.properties.st_mode);
1559        chown(outfile_fname, biggiestruct.properties.st_uid,
1560              biggiestruct.properties.st_gid);
1561        ubuf->actime = biggiestruct.properties.st_atime;
1562        ubuf->modtime = biggiestruct.properties.st_mtime;
1563        utime(outfile_fname, ubuf);
1564    }
1565
1566    paranoid_free(tmp);
1567    paranoid_free(outfile_fname);
1568    paranoid_free(command);
1569    paranoid_free(ntfsprog_command);
1570    paranoid_free(sz_devfile);
1571    paranoid_free(ntfsprog_fifo);
1572    g_loglevel = old_loglevel;
1573    return (retval);
1574}
1575
1576/**************************************************************************
1577 *END_RESTORE_A_BIGGIEFILE_FROM_STREAM                                    *
1578 **************************************************************************/
1579
1580
1581
1582/**
1583 * Restore @p tarball_fname from CD.
1584 * @param tarball_fname The filename of the tarball to restore (in /mnt/cdrom).
1585 * This will be used unmodified.
1586 * @param current_tarball_number The number (starting from 0) of the fileset
1587 * we're restoring now.
1588 * @param filelist The node structure containing the list of files to be
1589 * restored. If no file in the afioball is in this list, afio will still be
1590 * called, but nothing will be written.
1591 * @return 0 for success, nonzero for failure.
1592 */
1593int
1594restore_a_tarball_from_CD(char *tarball_fname,
1595                          long current_tarball_number,
1596                          struct s_node *filelist)
1597{
1598    int retval = 0;
1599    int res;
1600    char *p;
1601
1602  /** malloc **/
1603    char *command;
1604    char *tmp;
1605    char *filelist_name;
1606    char *filelist_subset_fname;
1607    char *executable;
1608    char *temp_log;
1609    char screen_message[100];
1610    long matches = 0;
1611    bool use_star;
1612    char *xattr_fname;
1613    char *acl_fname;
1614//  char files_to_restore_this_time_fname[MAX_STR_LEN];
1615
1616    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1617    malloc_string(command);
1618    malloc_string(tmp);
1619    malloc_string(filelist_name);
1620    malloc_string(filelist_subset_fname);
1621    malloc_string(executable);
1622    malloc_string(temp_log);
1623    malloc_string(xattr_fname);
1624    malloc_string(acl_fname);
1625
1626    log_msg(5, "Entering");
1627    filelist_subset_fname[0] = '\0';
1628    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1629//  sprintf(files_to_restore_this_time_fname, "/tmp/ftrttf.%d.%d", (int)getpid(), (int)random());
1630    sprintf(command, "mkdir -p %s/tmp", MNT_RESTORING);
1631    run_program_and_log_output(command, 9);
1632    sprintf(temp_log, "/tmp/%d.%d", (int) (random() % 32768),
1633            (int) (random() % 32768));
1634
1635    sprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld",
1636            current_tarball_number);
1637    if (length_of_file(filelist_name) <= 2) {
1638        log_msg(2, "There are _zero_ files in filelist '%s'",
1639                filelist_name);
1640        log_msg(2,
1641                "This is a bit silly (ask dev-team to fix mondo_makefilelist, please)");
1642        log_msg(2,
1643                "but it's non-critical. It's cosmetic. Don't worry about it.");
1644        retval = 0;
1645        goto leave_sub;
1646    }
1647    if (count_lines_in_file(filelist_name) <= 0
1648        || length_of_file(tarball_fname) <= 0) {
1649        log_msg(3, "length_of_file(%s) = %llu", tarball_fname,
1650                length_of_file(tarball_fname));
1651        sprintf(tmp, "Unable to restore fileset #%ld (CD I/O error)",
1652                current_tarball_number);
1653        log_to_screen(tmp);
1654        retval = 1;
1655        goto leave_sub;
1656    }
1657
1658    if (filelist) {
1659        sprintf(filelist_subset_fname, "/tmp/filelist-subset-%ld.tmp",
1660                current_tarball_number);
1661        if ((matches =
1662             save_filelist_entries_in_common(filelist_name, filelist,
1663                                             filelist_subset_fname,
1664                                             use_star))
1665            <= 0) {
1666            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1667            log_msg(1, tmp);
1668        } else {
1669            log_msg(3, "Saved fileset %ld's subset to %s",
1670                    current_tarball_number, filelist_subset_fname);
1671        }
1672        sprintf(screen_message, "Tarball #%ld --- %ld matches",
1673                current_tarball_number, matches);
1674        log_to_screen(screen_message);
1675    } else {
1676        filelist_subset_fname[0] = '\0';
1677    }
1678
1679    if (filelist == NULL || matches > 0) {
1680        if (g_getfattr) {
1681            sprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ,
1682                MNT_CDROM "/archives", current_tarball_number);
1683        }
1684        if (g_getfacl) {
1685            sprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives",
1686                current_tarball_number);
1687        }
1688        if (strstr(tarball_fname, ".bz2")) {
1689            strcpy(executable, "bzip2");
1690        } else if (strstr(tarball_fname, ".gz")) {
1691            strcpy(executable, "gzip");
1692        } else if (strstr(tarball_fname, ".lzo")) {
1693            strcpy(executable, "lzop");
1694        } else {
1695            executable[0] = '\0';
1696        }
1697        if (executable[0]) {
1698            sprintf(tmp, "which %s > /dev/null 2> /dev/null", executable);
1699            if (run_program_and_log_output(tmp, FALSE)) {
1700                log_to_screen
1701                    ("(compare_a_tarball) Compression program not found - oh no!");
1702                paranoid_MR_finish(1);
1703            }
1704            strcpy(tmp, executable);
1705            sprintf(executable, "-P %s -Z", tmp);
1706        }
1707#ifdef __FreeBSD__
1708#define BUFSIZE 512
1709#else
1710#define BUFSIZE (1024L*1024L)/TAPE_BLOCK_SIZE
1711#endif
1712
1713//      if (strstr(tarball_fname, ".star."))
1714        if (use_star) {
1715            sprintf(command,
1716                    "star -x -force-remove -U " STAR_ACL_SZ
1717                    " errctl= file=%s", tarball_fname);
1718            if (strstr(tarball_fname, ".bz2")) {
1719                strcat(command, " -bz");
1720            }
1721        } else {
1722            if (filelist_subset_fname[0] != '\0') {
1723                sprintf(command,
1724                        "afio -i -M 8m -b %ld -c %ld %s -w '%s' %s",
1725                        TAPE_BLOCK_SIZE,
1726                        BUFSIZE, executable, filelist_subset_fname,
1727//             files_to_restore_this_time_fname,
1728                        tarball_fname);
1729            } else {
1730                sprintf(command,
1731                        "afio -i -b %ld -c %ld -M 8m %s %s",
1732                        TAPE_BLOCK_SIZE,
1733                        BUFSIZE, executable, tarball_fname);
1734            }
1735        }
1736#undef BUFSIZE
1737        sprintf(command + strlen(command), " 2>> %s >> %s", temp_log,
1738                temp_log);
1739        log_msg(1, "command = '%s'", command);
1740        unlink(temp_log);
1741        res = system(command);
1742        if (res) {
1743            p = strstr(command, "-acl ");
1744            if (p) {
1745                p[0] = p[1] = p[2] = p[3] = ' ';
1746                log_msg(1, "new command = '%s'", command);
1747                res = system(command);
1748            }
1749        }
1750        if (res && length_of_file(temp_log) < 5) {
1751            res = 0;
1752        }
1753
1754        if (g_getfattr) {
1755            log_msg(1, "Setting fattr list %s", xattr_fname);
1756            if (length_of_file(xattr_fname) > 0) {
1757                res = set_fattr_list(filelist_subset_fname, xattr_fname);
1758                if (res) {
1759                    log_to_screen
1760                        ("Errors occurred while setting extended attributes");
1761                } else {
1762                    log_msg(1, "I set xattr OK");
1763                }
1764                retval += res;
1765            }
1766        }
1767        if (g_getfacl) {
1768            log_msg(1, "Setting acl list %s", acl_fname);
1769            if (length_of_file(acl_fname) > 0) {
1770                res = set_acl_list(filelist_subset_fname, acl_fname);
1771                if (res) {
1772                    log_to_screen
1773                        ("Errors occurred while setting access control lists");
1774                } else {
1775                    log_msg(1, "I set ACL OK");
1776                }
1777                retval += res;
1778            }
1779        }
1780        if (retval) {
1781            sprintf(command, "cat %s >> %s", temp_log, MONDO_LOGFILE);
1782            system(command);
1783            log_msg(2, "Errors occurred while processing fileset #%d",
1784                    current_tarball_number);
1785        } else {
1786            log_msg(2, "Fileset #%d processed OK", current_tarball_number);
1787        }
1788    }
1789    if (does_file_exist("/PAUSE")) {
1790        popup_and_OK
1791            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
1792    }
1793    unlink(filelist_subset_fname);
1794    unlink(xattr_fname);
1795    unlink(acl_fname);
1796    unlink(temp_log);
1797
1798  leave_sub:
1799    paranoid_free(command);
1800    paranoid_free(tmp);
1801    paranoid_free(filelist_name);
1802    paranoid_free(filelist_subset_fname);
1803    paranoid_free(executable);
1804    paranoid_free(temp_log);
1805    paranoid_free(xattr_fname);
1806    paranoid_free(acl_fname);
1807    log_msg(5, "Leaving");
1808    return (retval);
1809}
1810
1811/**************************************************************************
1812 *END_RESTORE_A_TARBALL_FROM_CD                                           *
1813 **************************************************************************/
1814
1815
1816/**
1817 * Restore a tarball from the currently opened stream.
1818 * @param bkpinfo The backup information structure. Fields used:
1819 * - @c bkpinfo->backup_media_type
1820 * - @c bkpinfo->media_device
1821 * - @c bkpinfo->zip_exe
1822 * @param tarball_fname The filename of the afioball to restore.
1823 * @param current_tarball_number The number (starting from 0) of the fileset
1824 * we're restoring now.
1825 * @param filelist The node structure containing the list of files to be
1826 * restored. If no file in the afioball is in this list, afio will still be
1827 * called, but nothing will be written.
1828 * @param size The size (in @b bytes) of the afioball.
1829 * @return 0 for success, nonzero for failure.
1830 */
1831int
1832restore_a_tarball_from_stream(char *tarball_fname,
1833                              long current_tarball_number,
1834                              struct s_node *filelist,
1835                              long long size, char *xattr_fname,
1836                              char *acl_fname)
1837{
1838    int retval = 0;
1839    int res = 0;
1840
1841  /** malloc add ***/
1842    char *tmp;
1843    char *command;
1844    char *afio_fname;
1845    char *filelist_fname;
1846    char *filelist_subset_fname;
1847    char *executable;
1848    long matches = 0;
1849    bool restore_this_fileset = FALSE;
1850    bool use_star;
1851
1852    assert(bkpinfo != NULL);
1853    assert_string_is_neither_NULL_nor_zerolength(tarball_fname);
1854    malloc_string(filelist_subset_fname);
1855    malloc_string(filelist_fname);
1856    malloc_string(afio_fname);
1857    malloc_string(executable);
1858    malloc_string(command);
1859    malloc_string(tmp);
1860    filelist_subset_fname[0] = '\0';
1861    /* to do it with a file... */
1862    use_star = (strstr(tarball_fname, ".star")) ? TRUE : FALSE;
1863    sprintf(tmp,
1864            "Restoring from fileset #%ld (%ld KB) on %s #%d",
1865            current_tarball_number, (long) size >> 10,
1866            media_descriptor_string(bkpinfo->backup_media_type),
1867            g_current_media_number);
1868    log_msg(2, tmp);
1869    run_program_and_log_output("mkdir -p " MNT_RESTORING "/tmp", FALSE);
1870
1871  /****************************************************************************
1872   * Use RAMDISK's /tmp; saves time; oh wait, it's too small                  *
1873   * Well, pipe from tape to afio, then; oh wait, can't do that either: bug   *
1874   * in afio or someting; oh darn.. OK, use tmpfs :-)                         *
1875   ****************************************************************************/
1876    filelist_fname[0] = filelist_subset_fname[0] = '\0';
1877    sprintf(afio_fname, "/tmp/tmpfs/archive.tmp.%ld",
1878            current_tarball_number);
1879    sprintf(filelist_fname, "%s/filelist.%ld", bkpinfo->tmpdir,
1880            current_tarball_number);
1881    sprintf(filelist_subset_fname, "%s/filelist-subset-%ld.tmp",
1882            bkpinfo->tmpdir, current_tarball_number);
1883//  sprintf(filelist_fname, "/tmp/tmpfs/temp-filelist.%ld", current_tarball_number);
1884    res = read_file_from_stream_to_file(afio_fname, size);
1885    if (strstr(tarball_fname, ".star")) {
1886        bkpinfo->use_star = TRUE;
1887    }
1888    if (res) {
1889        log_msg(1, "Warning - error reading afioball from tape");
1890    }
1891    if (bkpinfo->compression_level == 0) {
1892        executable[0] = '\0';
1893    } else {
1894        if (bkpinfo->use_star) {
1895            strcpy(executable, " -bz");
1896        } else {
1897            sprintf(executable, "-P %s -Z", bkpinfo->zip_exe);
1898        }
1899    }
1900
1901    if (!filelist)              // if unconditional restore then restore entire fileset
1902    {
1903        restore_this_fileset = TRUE;
1904    } else                      // If restoring selectively then get TOC from tarball
1905    {
1906        if (strstr(tarball_fname, ".star.")) {
1907            use_star = TRUE;
1908            sprintf(command, "star -t file=%s %s", afio_fname, executable);
1909        } else {
1910            use_star = FALSE;
1911            sprintf(command, "afio -t -M 8m -b %ld %s %s", TAPE_BLOCK_SIZE,
1912                    executable, afio_fname);
1913        }
1914        sprintf(command + strlen(command), " > %s 2>> %s", filelist_fname,
1915                MONDO_LOGFILE);
1916        log_msg(1, "command = %s", command);
1917        if (system(command)) {
1918            log_msg(4, "Warning - error occurred while retrieving TOC");
1919        }
1920        if ((matches =
1921             save_filelist_entries_in_common(filelist_fname, filelist,
1922                                             filelist_subset_fname,
1923                                             use_star))
1924            <= 0 || length_of_file(filelist_subset_fname) < 2) {
1925            if (length_of_file(filelist_subset_fname) < 2) {
1926                log_msg(1, "No matches found in fileset %ld",
1927                        current_tarball_number);
1928            }
1929            sprintf(tmp, "Skipping fileset %ld", current_tarball_number);
1930            log_msg(2, tmp);
1931            restore_this_fileset = FALSE;
1932        } else {
1933            log_msg(5, "%ld matches. Saved fileset %ld's subset to %s",
1934                    matches, current_tarball_number,
1935                    filelist_subset_fname);
1936            restore_this_fileset = TRUE;
1937        }
1938    }
1939
1940// Concoct the call to star/afio to restore files
1941    if (strstr(tarball_fname, ".star."))    // star
1942    {
1943        sprintf(command, "star -x file=%s %s", afio_fname, executable);
1944        if (filelist) {
1945            sprintf(command + strlen(command), " list=%s",
1946                    filelist_subset_fname);
1947        }
1948    } else                      // afio
1949    {
1950        sprintf(command, "afio -i -M 8m -b %ld %s", TAPE_BLOCK_SIZE,
1951                executable);
1952        if (filelist) {
1953            sprintf(command + strlen(command), " -w %s",
1954                    filelist_subset_fname);
1955        }
1956        sprintf(command + strlen(command), " %s", afio_fname);
1957    }
1958    sprintf(command + strlen(command), " 2>> %s", MONDO_LOGFILE);
1959
1960// Call if IF there are files to restore (selectively/unconditionally)
1961    if (restore_this_fileset) {
1962        log_msg(1, "Calling command='%s'", command);
1963        paranoid_system(command);
1964
1965        if (g_getfattr) {
1966            iamhere("Restoring xattr stuff");
1967            res = set_fattr_list(filelist_subset_fname, xattr_fname);
1968            if (res) {
1969                log_msg(1, "Errors occurred while setting xattr");
1970            } else {
1971                log_msg(1, "I set xattr OK");
1972            }
1973            retval += res;
1974        }
1975
1976        if (g_getfacl) {
1977            iamhere("Restoring acl stuff");
1978            res = set_acl_list(filelist_subset_fname, acl_fname);
1979            if (res) {
1980                log_msg(1, "Errors occurred while setting ACL");
1981            } else {
1982                log_msg(1, "I set ACL OK");
1983            }
1984            retval += res;
1985        }
1986
1987    } else {
1988        log_msg(1, "NOT CALLING '%s'", command);
1989    }
1990
1991    if (does_file_exist("/PAUSE") && current_tarball_number >= 50) {
1992        log_to_screen("Paused after set %ld", current_tarball_number);
1993        popup_and_OK("Pausing. Press ENTER to continue.");
1994    }
1995
1996    unlink(filelist_subset_fname);
1997    unlink(filelist_fname);
1998    unlink(afio_fname);
1999
2000    paranoid_free(filelist_subset_fname);
2001    paranoid_free(filelist_fname);
2002    paranoid_free(afio_fname);
2003    paranoid_free(command);
2004    paranoid_free(tmp);
2005    return (retval);
2006}
2007
2008/**************************************************************************
2009 *END_RESTORE_A_TARBALL_FROM_STREAM                                       *
2010 **************************************************************************/
2011
2012
2013
2014
2015/**
2016 * Restore all biggiefiles from all media in this CD backup.
2017 * The CD with the last afioball should be currently mounted.
2018 * @param bkpinfo The backup information structure. @c backup_media_type is the
2019 * only field used in this function.
2020 * @param filelist The node structure containing the list of files to be
2021 * restored. If a prospective biggiefile is not in this list, it will be ignored.
2022 * @return 0 for success, nonzero for failure.
2023 */
2024int
2025restore_all_biggiefiles_from_CD(struct s_node *filelist)
2026{
2027    int retval = 0;
2028    int res;
2029    long noof_biggiefiles, bigfileno = 0, total_slices;
2030  /** malloc **/
2031    char *tmp;
2032    bool just_changed_cds = FALSE, finished;
2033    char *xattr_fname;
2034    char *acl_fname;
2035    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
2036    char *pathname_of_last_biggie_restored;
2037    FILE *fbw = NULL;
2038
2039    malloc_string(xattr_fname);
2040    malloc_string(acl_fname);
2041    malloc_string(tmp);
2042    malloc_string(biggies_whose_EXATs_we_should_set);
2043    malloc_string(pathname_of_last_biggie_restored);
2044    assert(bkpinfo != NULL);
2045
2046    sprintf(biggies_whose_EXATs_we_should_set,
2047            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2048    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2049        log_msg(1, "Warning - cannot openout %s",
2050                biggies_whose_EXATs_we_should_set);
2051    }
2052
2053    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2054    total_slices = atol(tmp);
2055    sprintf(tmp, "Reassembling large files      ");
2056    mvaddstr_and_log_it(g_currentY, 0, tmp);
2057    if (length_of_file(BIGGIELIST) < 6) {
2058        log_msg(1, "OK, no biggielist; not restoring biggiefiles");
2059        return (0);
2060    }
2061    noof_biggiefiles = count_lines_in_file(BIGGIELIST);
2062    if (noof_biggiefiles <= 0) {
2063        log_msg(2,
2064                "OK, no biggiefiles in biggielist; not restoring biggiefiles");
2065        return (0);
2066    }
2067    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2068            noof_biggiefiles);
2069    log_msg(2, tmp);
2070
2071    open_progress_form("Reassembling large files",
2072                       "I am now reassembling all the large files.",
2073                       "Please wait. This may take some time.",
2074                       "", total_slices);
2075    for (bigfileno = 0, finished = FALSE; !finished;) {
2076        log_msg(2, "Thinking about restoring bigfile %ld", bigfileno + 1);
2077        if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
2078            log_msg(3,
2079                    "...but its first slice isn't on this CD. Perhaps this was a selective restore?");
2080            log_msg(3, "Cannot find bigfile #%ld 's first slice on %s #%d",
2081                    bigfileno + 1,
2082                    media_descriptor_string(bkpinfo->backup_media_type),
2083                    g_current_media_number);
2084            log_msg(3, "Slicename would have been %s",
2085                    slice_fname(bigfileno + 1, 0, ARCHIVES_PATH, ""));
2086            // I'm not positive 'just_changed_cds' is even necessary...
2087            if (just_changed_cds) {
2088                just_changed_cds = FALSE;
2089                log_msg(3,
2090                        "I'll continue to scan this CD for bigfiles to be restored.");
2091            } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
2092                insist_on_this_cd_number(++g_current_media_number);
2093                sprintf(tmp, "Restoring from %s #%d",
2094                        media_descriptor_string(bkpinfo->backup_media_type),
2095                        g_current_media_number);
2096                log_to_screen(tmp);
2097                just_changed_cds = TRUE;
2098            } else {
2099                log_msg(2, "There was no bigfile #%ld. That's OK.",
2100                        bigfileno + 1);
2101                log_msg(2, "I'm going to stop restoring bigfiles now.");
2102                finished = TRUE;
2103            }
2104        } else {
2105            just_changed_cds = FALSE;
2106            sprintf(tmp, "Restoring big file %ld", bigfileno + 1);
2107            update_progress_form(tmp);
2108            res =
2109                restore_a_biggiefile_from_CD(bigfileno, filelist, pathname_of_last_biggie_restored);
2110            iamhere(pathname_of_last_biggie_restored);
2111            if (fbw && pathname_of_last_biggie_restored[0]) {
2112                fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2113            }
2114            retval += res;
2115            bigfileno++;
2116
2117        }
2118    }
2119
2120    if (fbw) {
2121        fclose(fbw);
2122        if (g_getfattr) {
2123            sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2124            if (length_of_file(xattr_fname) > 0) {
2125                set_fattr_list(biggies_whose_EXATs_we_should_set, xattr_fname);
2126            }
2127        }
2128        if (g_getfacl) {
2129            sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, ARCHIVES_PATH);
2130            if (length_of_file(acl_fname) > 0) {
2131                set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2132            }
2133        }
2134    }
2135    if (does_file_exist("/PAUSE")) {
2136        popup_and_OK
2137            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2138    }
2139    close_progress_form();
2140    if (retval) {
2141        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2142    } else {
2143        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2144    }
2145    paranoid_free(xattr_fname);
2146    paranoid_free(acl_fname);
2147    paranoid_free(tmp);
2148    paranoid_free(biggies_whose_EXATs_we_should_set);
2149    paranoid_free(pathname_of_last_biggie_restored);
2150    return (retval);
2151}
2152
2153/**************************************************************************
2154 *END_RESTORE_ALL_BIGGIFILES_FROM_CD                                      *
2155 **************************************************************************/
2156
2157
2158
2159/**
2160 * Restore all afioballs from all CDs in the backup.
2161 * The first CD should be inserted (if not, it will be asked for).
2162 * @param bkpinfo The backup information structure. @c backup_media_type is the
2163 * only field used in @e this function.
2164 * @param filelist The node structure containing the list of files to be
2165 * restored. If no file in some particular afioball is in this list, afio will
2166 * still be called for that fileset, but nothing will be written.
2167 * @return 0 for success, or the number of filesets that failed.
2168 */
2169int
2170restore_all_tarballs_from_CD(struct s_node *filelist)
2171{
2172    int retval = 0;
2173    int res;
2174    int attempts;
2175    long current_tarball_number = 0;
2176    long max_val;
2177  /**malloc ***/
2178    char *tmp;
2179    char *tarball_fname;
2180    char *progress_str;
2181    char *comment;
2182
2183    malloc_string(tmp);
2184    malloc_string(tarball_fname);
2185    malloc_string(progress_str);
2186    malloc_string(comment);
2187
2188    assert(bkpinfo != NULL);
2189
2190    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2191    log_msg(2,
2192            "Insisting on 1st CD, so that I can have a look at LAST-FILELIST-NUMBER");
2193    if (g_current_media_number != 1) {
2194        log_msg(3, "OK, that's jacked up.");
2195        g_current_media_number = 1;
2196    }
2197    insist_on_this_cd_number(g_current_media_number);
2198    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2199    max_val = atol(tmp) + 1;
2200    sprintf(progress_str, "Restoring from %s #%d",
2201            media_descriptor_string(bkpinfo->backup_media_type),
2202            g_current_media_number);
2203    log_to_screen(progress_str);
2204    open_progress_form("Restoring from archives",
2205                       "Restoring data from the archives.",
2206                       "Please wait. This may take some time.",
2207                       progress_str, max_val);
2208    for (;;) {
2209        insist_on_this_cd_number(g_current_media_number);
2210        update_progress_form(progress_str);
2211        sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2",
2212                current_tarball_number);
2213        if (!does_file_exist(tarball_fname)) {
2214            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz",
2215                current_tarball_number);
2216        }
2217        if (!does_file_exist(tarball_fname)) {
2218            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo",
2219                    current_tarball_number);
2220        }
2221        if (!does_file_exist(tarball_fname)) {
2222            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.",
2223                    current_tarball_number);
2224        }
2225        if (!does_file_exist(tarball_fname)) {
2226            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2",
2227                    current_tarball_number);
2228        }
2229        if (!does_file_exist(tarball_fname)) {
2230            sprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.",
2231                    current_tarball_number);
2232        }
2233        if (!does_file_exist(tarball_fname)) {
2234            if (current_tarball_number == 0) {
2235                log_to_screen
2236                    ("No tarballs. Strange. Maybe you only backed up freakin' big files?");
2237                return (0);
2238            }
2239            if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
2240                || system("find " MNT_CDROM
2241                          "/archives/slice* > /dev/null 2> /dev/null") ==
2242                0) {
2243                break;
2244            }
2245            g_current_media_number++;
2246            sprintf(progress_str, "Restoring from %s #%d",
2247                    media_descriptor_string(bkpinfo->backup_media_type),
2248                    g_current_media_number);
2249            log_to_screen(progress_str);
2250        } else {
2251            sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2252                    current_tarball_number,
2253                    media_descriptor_string(bkpinfo->backup_media_type),
2254                    g_current_media_number);
2255//    log_msg(3, "progress_str = %s", progress_str);
2256            for (res = 999, attempts = 0; attempts < 3 && res != 0;
2257                 attempts++) {
2258                res =
2259                    restore_a_tarball_from_CD(tarball_fname,
2260                                              current_tarball_number,
2261                                              filelist);
2262            }
2263            sprintf(tmp, "%s #%d, fileset #%ld - restore ",
2264                    media_descriptor_string(bkpinfo->backup_media_type),
2265                    g_current_media_number, current_tarball_number);
2266            if (res) {
2267                strcat(tmp, "reported errors");
2268            } else if (attempts > 1) {
2269                strcat(tmp, "succeeded");
2270            } else {
2271                strcat(tmp, "succeeded");
2272            }
2273            if (attempts > 1) {
2274                sprintf(tmp + strlen(tmp), " (%d attempts) - review logs",
2275                        attempts);
2276            }
2277            strcpy(comment, tmp);
2278            if (attempts > 1) {
2279                log_to_screen(comment);
2280            }
2281
2282            retval += res;
2283            current_tarball_number++;
2284            g_current_progress++;
2285        }
2286    }
2287    close_progress_form();
2288    if (retval) {
2289        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2290    } else {
2291        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2292    }
2293    paranoid_free(tmp);
2294    paranoid_free(tarball_fname);
2295    paranoid_free(progress_str);
2296    paranoid_free(comment);
2297
2298    return (retval);
2299}
2300
2301/**************************************************************************
2302 *END_RESTORE_ALL_TARBALLS_FROM_CD                                        *
2303 **************************************************************************/
2304
2305
2306
2307/**
2308 * Restore all biggiefiles from the currently opened stream.
2309 * @param bkpinfo The backup information structure. Passed to other functions.
2310 * @param filelist The node structure containing the list of files to be
2311 * restored. If a prospective biggiefile is not in the list, it will be ignored.
2312 * @return 0 for success, or the number of biggiefiles that failed.
2313 */
2314int
2315restore_all_biggiefiles_from_stream(struct s_node *filelist)
2316{
2317    long noof_biggiefiles;
2318    long current_bigfile_number = 0;
2319    long total_slices;
2320
2321    int retval = 0;
2322    int res = 0;
2323    int ctrl_chr;
2324
2325  /** malloc add ****/
2326    char *tmp;
2327    char *biggie_fname;
2328    char *biggie_cksum;
2329    char *xattr_fname;
2330    char *acl_fname;
2331    char *p;
2332    char *pathname_of_last_biggie_restored;
2333    char *biggies_whose_EXATs_we_should_set;    // EXtended ATtributes
2334    long long biggie_size;
2335    FILE *fbw = NULL;
2336
2337    malloc_string(tmp);
2338    malloc_string(biggie_fname);
2339    malloc_string(biggie_cksum);
2340    malloc_string(xattr_fname);
2341    malloc_string(acl_fname);
2342    malloc_string(biggies_whose_EXATs_we_should_set);
2343    malloc_string(pathname_of_last_biggie_restored);
2344    assert(bkpinfo != NULL);
2345
2346    read_cfg_var(g_mondo_cfg_file, "total-slices", tmp);
2347
2348    total_slices = atol(tmp);
2349    sprintf(tmp, "Reassembling large files      ");
2350    if (g_getfattr) {
2351        sprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2352    }
2353    if (g_getfacl) {
2354        sprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
2355    }
2356    mvaddstr_and_log_it(g_currentY, 0, tmp);
2357    sprintf(biggies_whose_EXATs_we_should_set,
2358            "%s/biggies-whose-EXATs-we-should-set", bkpinfo->tmpdir);
2359    if (!(fbw = fopen(biggies_whose_EXATs_we_should_set, "w"))) {
2360        log_msg(1, "Warning - cannot openout %s",
2361                biggies_whose_EXATs_we_should_set);
2362    }
2363// get xattr and acl files if they're there
2364    res =
2365        read_header_block_from_stream(&biggie_size, biggie_fname,
2366                                      &ctrl_chr);
2367    if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2368        res =
2369            read_EXAT_files_from_tape(&biggie_size, biggie_fname,
2370                                      &ctrl_chr, xattr_fname, acl_fname);
2371    }
2372
2373    noof_biggiefiles = atol(biggie_fname);
2374    sprintf(tmp, "OK, there are %ld biggiefiles in the archives",
2375            noof_biggiefiles);
2376    log_msg(2, tmp);
2377    open_progress_form("Reassembling large files",
2378                       "I am now reassembling all the large files.",
2379                       "Please wait. This may take some time.",
2380                       "", total_slices);
2381
2382    for (res =
2383         read_header_block_from_stream(&biggie_size, biggie_fname,
2384                                       &ctrl_chr);
2385         ctrl_chr != BLK_STOP_BIGGIEFILES;
2386         res =
2387         read_header_block_from_stream(&biggie_size, biggie_fname,
2388                                       &ctrl_chr)) {
2389        if (ctrl_chr != BLK_START_A_NORMBIGGIE
2390            && ctrl_chr != BLK_START_A_PIHBIGGIE) {
2391            wrong_marker(BLK_START_A_NORMBIGGIE, ctrl_chr);
2392        }
2393        p = strrchr(biggie_fname, '/');
2394        if (!p) {
2395            p = biggie_fname;
2396        } else {
2397            p++;
2398        }
2399        sprintf(tmp, "Restoring big file %ld (%lld K)",
2400                current_bigfile_number + 1, biggie_size / 1024);
2401        update_progress_form(tmp);
2402        res = restore_a_biggiefile_from_stream(biggie_fname,
2403                                               current_bigfile_number,
2404                                               biggie_cksum,
2405                                               biggie_size,
2406                                               filelist, ctrl_chr,
2407                                               pathname_of_last_biggie_restored);
2408        log_msg(1, "I believe I have restored %s",
2409                pathname_of_last_biggie_restored);
2410        if (fbw && pathname_of_last_biggie_restored[0]) {
2411            fprintf(fbw, "%s\n", pathname_of_last_biggie_restored);
2412        }
2413        retval += res;
2414        current_bigfile_number++;
2415
2416    }
2417    if (current_bigfile_number != noof_biggiefiles
2418        && noof_biggiefiles != 0) {
2419        sprintf(tmp, "Warning - bigfileno=%ld but noof_biggiefiles=%ld\n",
2420                current_bigfile_number, noof_biggiefiles);
2421    } else {
2422        sprintf(tmp,
2423                "%ld biggiefiles in biggielist.txt; %ld biggiefiles processed today.",
2424                noof_biggiefiles, current_bigfile_number);
2425    }
2426    log_msg(1, tmp);
2427
2428    if (fbw) {
2429        fclose(fbw);
2430        if (length_of_file(biggies_whose_EXATs_we_should_set) > 2) {
2431            iamhere("Setting biggie-EXATs");
2432            if (g_getfattr) {
2433                if (length_of_file(xattr_fname) > 0) {
2434                    log_msg(1, "set_fattr_List(%s,%s)",
2435                        biggies_whose_EXATs_we_should_set, xattr_fname);
2436                    set_fattr_list(biggies_whose_EXATs_we_should_set,
2437                               xattr_fname);
2438                }
2439            }
2440            if (g_getfacl) {
2441                if (length_of_file(acl_fname) > 0) {
2442                    log_msg(1, "set_acl_list(%s,%s)",
2443                            biggies_whose_EXATs_we_should_set, acl_fname);
2444                    set_acl_list(biggies_whose_EXATs_we_should_set, acl_fname);
2445                }
2446            }
2447        } else {
2448            iamhere
2449                ("No biggiefiles selected. So, no biggie-EXATs to set.");
2450        }
2451    }
2452    if (does_file_exist("/PAUSE")) {
2453        popup_and_OK
2454            ("Press ENTER to go on. Delete /PAUSE to stop these pauses.");
2455    }
2456
2457    close_progress_form();
2458    if (retval) {
2459        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2460    } else {
2461        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2462    }
2463    paranoid_free(biggies_whose_EXATs_we_should_set);
2464    paranoid_free(pathname_of_last_biggie_restored);
2465    paranoid_free(biggie_fname);
2466    paranoid_free(biggie_cksum);
2467    paranoid_free(xattr_fname);
2468    paranoid_free(acl_fname);
2469    paranoid_free(tmp);
2470    return (retval);
2471}
2472
2473/**************************************************************************
2474 *END_RESTORE_ALL_BIGGIEFILES_FROM_STREAM                                 *
2475 **************************************************************************/
2476
2477
2478
2479
2480
2481
2482/**
2483 * Restore all afioballs from the currently opened tape stream.
2484 * @param bkpinfo The backup information structure. Fields used:
2485 * - @c bkpinfo->backup_media_type
2486 * - @c bkpinfo->restore_path
2487 * @param filelist The node structure containing the list of files to be
2488 * restored. If no file in an afioball is in this list, afio will still be
2489 * called for that fileset, but nothing will be written.
2490 * @return 0 for success, or the number of filesets that failed.
2491 */
2492int
2493restore_all_tarballs_from_stream(struct s_node *filelist)
2494{
2495    int retval = 0;
2496    int res;
2497    long current_afioball_number = 0;
2498    int ctrl_chr;
2499    long max_val /*, total_noof_files */ ;
2500
2501  /** malloc **/
2502    char *tmp;
2503    char *progress_str;
2504    char *tmp_fname;
2505    char *xattr_fname;
2506    char *acl_fname;
2507
2508    long long tmp_size;
2509
2510    malloc_string(tmp);
2511    malloc_string(progress_str);
2512    malloc_string(tmp_fname);
2513    assert(bkpinfo != NULL);
2514    malloc_string(xattr_fname);
2515    malloc_string(acl_fname);
2516    mvaddstr_and_log_it(g_currentY, 0, "Restoring from archives");
2517    read_cfg_var(g_mondo_cfg_file, "last-filelist-number", tmp);
2518    max_val = atol(tmp) + 1;
2519
2520    chdir(bkpinfo->restore_path);   /* I don't know why this is needed _here_ but it seems to be. -HR, 02/04/2002 */
2521
2522    run_program_and_log_output("pwd", 5);
2523
2524    sprintf(progress_str, "Restoring from media #%d",
2525            g_current_media_number);
2526    log_to_screen(progress_str);
2527    open_progress_form("Restoring from archives",
2528                       "Restoring data from the archives.",
2529                       "Please wait. This may take some time.",
2530                       progress_str, max_val);
2531
2532    log_msg(3, "hey");
2533
2534    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2535    if (res) {
2536        log_msg(2, "Warning - error reading afioball from tape");
2537    }
2538    retval += res;
2539    if (ctrl_chr != BLK_START_AFIOBALLS) {
2540        wrong_marker(BLK_START_AFIOBALLS, ctrl_chr);
2541    }
2542    log_msg(2, "ho");
2543    res = read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2544    while (ctrl_chr != BLK_STOP_AFIOBALLS) {
2545        update_progress_form(progress_str);
2546        if (g_getfattr) {
2547            sprintf(xattr_fname, "%s/xattr-subset-%ld.tmp", bkpinfo->tmpdir,
2548                current_afioball_number);
2549            unlink(xattr_fname);
2550        }
2551        if (g_getfacl) {
2552            sprintf(acl_fname, "%s/acl-subset-%ld.tmp", bkpinfo->tmpdir,
2553                current_afioball_number);
2554            unlink(acl_fname);
2555        }
2556        if (ctrl_chr == BLK_START_EXTENDED_ATTRIBUTES) {
2557            iamhere("Reading EXAT files from tape");
2558            res =
2559                read_EXAT_files_from_tape(&tmp_size, tmp_fname,
2560                                          &ctrl_chr, xattr_fname,
2561                                          acl_fname);
2562        }
2563        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
2564            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
2565        }
2566        sprintf(tmp,
2567                "Restoring from fileset #%ld (name=%s, size=%ld K)",
2568                current_afioball_number, tmp_fname, (long) tmp_size >> 10);
2569        res =
2570            restore_a_tarball_from_stream(tmp_fname,
2571                                          current_afioball_number,
2572                                          filelist, tmp_size, xattr_fname,
2573                                          acl_fname);
2574        retval += res;
2575        if (res) {
2576            sprintf(tmp, "Fileset %ld - errors occurred",
2577                    current_afioball_number);
2578            log_to_screen(tmp);
2579        }
2580        res =
2581            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2582        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
2583            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
2584        }
2585
2586        current_afioball_number++;
2587        g_current_progress++;
2588        sprintf(progress_str, "Restoring from fileset #%ld on %s #%d",
2589                current_afioball_number,
2590                media_descriptor_string(bkpinfo->backup_media_type),
2591                g_current_media_number);
2592        res =
2593            read_header_block_from_stream(&tmp_size, tmp_fname, &ctrl_chr);
2594        if (g_getfattr) {
2595            unlink(xattr_fname);
2596        }
2597        if (g_getfacl) {
2598            unlink(acl_fname);
2599        }
2600    }                           // next
2601    log_msg(1, "All done with afioballs");
2602    close_progress_form();
2603    if (retval) {
2604        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
2605    } else {
2606        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2607    }
2608    paranoid_free(tmp);
2609    paranoid_free(progress_str);
2610    paranoid_free(tmp_fname);
2611    paranoid_free(xattr_fname);
2612    paranoid_free(acl_fname);
2613    return (retval);
2614}
2615
2616/**************************************************************************
2617 *END_ RESTORE_ALL_TARBALLS_FROM_STREAM                                   *
2618 **************************************************************************/
2619
2620/* @} - end of LLrestoreGroup */
2621
2622
2623/**
2624 * Restore all files in @p filelist.
2625 * @param bkpinfo The backup information structure. Most fields are used.
2626 * @param filelist The node structure containing the list of files to be
2627 * restored.
2628 * @return 0 for success, or the number of afioballs and biggiefiles that failed.
2629 * @ingroup restoreGroup
2630 */
2631int restore_everything(struct s_node *filelist)
2632{
2633    int resA;
2634    int resB;
2635
2636  /** mallco ***/
2637    char *cwd;
2638    char *newpath;
2639    char *tmp;
2640    assert(bkpinfo != NULL);
2641
2642    malloc_string(cwd);
2643    malloc_string(newpath);
2644    malloc_string(tmp);
2645    log_msg(2, "restore_everything() --- starting");
2646    g_current_media_number = 1;
2647    getcwd(cwd, MAX_STR_LEN - 1);
2648    sprintf(tmp, "mkdir -p %s", bkpinfo->restore_path);
2649    run_program_and_log_output(tmp, FALSE);
2650    log_msg(1, "Changing dir to %s", bkpinfo->restore_path);
2651    chdir(bkpinfo->restore_path);
2652    getcwd(newpath, MAX_STR_LEN - 1);
2653    log_msg(1, "path is now %s", newpath);
2654    log_msg(1, "restoring everything");
2655    if (!find_home_of_exe("petris") && !g_text_mode) {
2656        newtDrawRootText(0, g_noof_rows - 2,
2657                         "Press ALT-<left cursor> twice to play Petris :-) ");
2658        newtRefresh();
2659    }
2660    mvaddstr_and_log_it(g_currentY, 0, "Preparing to read your archives");
2661    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
2662        mount_cdrom();
2663        mvaddstr_and_log_it(g_currentY++, 0,
2664                            "Restoring OS and data from streaming media");
2665        if (bkpinfo->backup_media_type == cdstream) {
2666            openin_cdstream();
2667        } else {
2668            assert_string_is_neither_NULL_nor_zerolength(bkpinfo->media_device);
2669            openin_tape();
2670        }
2671        resA = restore_all_tarballs_from_stream(filelist);
2672        resB = restore_all_biggiefiles_from_stream(filelist);
2673        if (bkpinfo->backup_media_type == cdstream) {
2674            closein_cdstream();
2675        } else {
2676            closein_tape();
2677        }
2678    } else {
2679        mvaddstr_and_log_it(g_currentY++, 0,
2680                            "Restoring OS and data from CD       ");
2681        mount_cdrom();
2682        resA = restore_all_tarballs_from_CD(filelist);
2683        resB = restore_all_biggiefiles_from_CD(filelist);
2684    }
2685    chdir(cwd);
2686    if (resA + resB) {
2687        log_to_screen("Errors occurred while data was being restored.");
2688    }
2689    if (length_of_file("/etc/raidtab") > 0) {
2690        log_msg(2, "Copying local raidtab to restored filesystem");
2691        run_program_and_log_output("cp -f /etc/raidtab " MNT_RESTORING
2692                                   "/etc/raidtab", FALSE);
2693    }
2694    kill_petris();
2695    log_msg(2, "restore_everything() --- leaving");
2696    paranoid_free(cwd);
2697    paranoid_free(newpath);
2698    paranoid_free(tmp);
2699    return (resA + resB);
2700}
2701
2702/**************************************************************************
2703 *END_RESTORE_EVERYTHING                                                  *
2704 **************************************************************************/
2705
2706
2707
2708/**
2709 * @brief Haha. You wish! (This function is not implemented :-)
2710 */
2711int
2712restore_live_from_monitas_server(char *monitas_device,
2713                                 char *restore_this_directory,
2714                                 char *restore_here)
2715     /* NB: bkpinfo hasn't been populated yet, except for ->tmp which is "/tmp" */
2716{
2717    FILE *fout;
2718    int retval = 0;
2719    int i;
2720    int j;
2721    struct mountlist_itself the_mountlist;
2722    static struct raidlist_itself the_raidlist;
2723  /** malloc **/
2724    char tmp[MAX_STR_LEN + 1];
2725    char command[MAX_STR_LEN + 1];
2726    char datablock[256 * 1024];
2727    char datadisks_fname[MAX_STR_LEN + 1];
2728    long k;
2729    long length;
2730    long long llt;
2731    struct s_node *filelist = NULL;
2732    assert(bkpinfo != NULL);
2733    assert_string_is_neither_NULL_nor_zerolength(monitas_device);
2734    assert(restore_this_directory != NULL);
2735    assert(restore_here != NULL);
2736
2737    sprintf(tmp, "restore_here = '%s'", restore_here);
2738
2739    log_msg(2, tmp);
2740
2741    log_msg(2, "restore_live_from_monitas_server() - starting");
2742    unlink("/tmp/mountlist.txt");
2743    unlink("/tmp/filelist.full");
2744    unlink("/tmp/biggielist.txt");
2745    if (restore_here[0] == '\0') {
2746        strcpy(bkpinfo->restore_path, MNT_RESTORING);
2747    } else {
2748        strcpy(bkpinfo->restore_path, restore_here);
2749    }
2750    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2751    sprintf(tmp, "FYI - data will be restored to %s",
2752            bkpinfo->restore_path);
2753    log_msg(3, tmp);
2754    log_msg(3, "FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI FYI");
2755    sprintf(datadisks_fname, "/tmp/mondorestore.datadisks.%d",
2756            (int) (random() % 32768));
2757    chdir(bkpinfo->tmpdir);
2758
2759    sprintf(command, "cat %s", monitas_device);
2760    g_tape_stream = popen(command, "r");    // for compatibility with openin_tape()
2761    if (!(fout = fopen(datadisks_fname, "w"))) {
2762        log_OS_error(datadisks_fname);
2763        return (1);
2764    }
2765    for (i = 0; i < 32; i++) {
2766        for (j = 0; j < 4; j++) {
2767            for (length = k = 0; length < 256 * 1024; length += k) {
2768                k = fread(datablock + length, 1, 256 * 1024 - length,
2769                          g_tape_stream);
2770            }
2771            fwrite(datablock, 1, length, fout);
2772            g_tape_posK += length;
2773        }
2774    }
2775    paranoid_fclose(fout);
2776    sprintf(command,
2777            "tar -zxvf %s tmp/mondo-restore.cfg tmp/mountlist.txt tmp/filelist.full tmp/biggielist.txt",
2778            datadisks_fname);
2779    run_program_and_log_output(command, 4);
2780    read_header_block_from_stream(&llt, tmp, &i);
2781    read_header_block_from_stream(&llt, tmp, &i);
2782
2783    unlink(datadisks_fname);
2784    read_cfg_file_into_bkpinfo(g_mondo_cfg_file);
2785    retval = load_mountlist(&the_mountlist, g_mountlist_fname); // in case read_cfg_file_into_bkpinfo   strcpy(bkpinfo->media_device, monitas_device);
2786
2787
2788    load_raidtab_into_raidlist(&the_raidlist, RAIDTAB_FNAME);
2789    iamhere("FIXME");
2790    fatal_error("This will fail");
2791    sprintf(command,
2792            "grep -E '^%s.*$' %s > %s",
2793            restore_this_directory, g_filelist_full, g_filelist_full);
2794    if (system(command)) {
2795        retval++;
2796        log_to_screen
2797            ("Error(s) occurred while processing filelist and wildcard");
2798    }
2799    iamhere("FIXME");
2800    fatal_error("This will fail");
2801    sprintf(command,
2802            "grep -E '^%s.*$' %s > %s",
2803            restore_this_directory, g_biggielist_txt, g_biggielist_txt);
2804    if (system(command)) {
2805        log_msg(1,
2806                "Error(s) occurred while processing biggielist and wildcard");
2807    }
2808    sprintf(command, "touch %s", g_biggielist_txt);
2809    run_program_and_log_output(command, FALSE);
2810//  filelist = load_filelist(g_filelist_restthese);  // FIXME --- this probably doesn't work because it doesn't include the biggiefiles
2811    retval += restore_everything(filelist);
2812    free_filelist(filelist);
2813    log_msg(2, "--------End of restore_live_from_monitas_server--------");
2814    return (retval);
2815}
2816
2817/**************************************************************************
2818 *END_RESTORE_LIVE_FROM_MONITAS_SERVER                                    *
2819 **************************************************************************/
2820
2821
2822
2823
2824extern void wait_until_software_raids_are_prepped(char *, int);
2825
2826
2827char which_restore_mode(void);
2828
2829
2830/**
2831 * Log a "don't panic" message to the logfile.
2832 */
2833void welcome_to_mondorestore()
2834{
2835    log_msg(0, "-------------- Mondo Restore v%s -------------", PACKAGE_VERSION);
2836    log_msg(0,
2837            "DON'T PANIC! Mondorestore logs almost everything, so please ");
2838    log_msg(0,
2839            "don't break out in a cold sweat just because you see a few  ");
2840    log_msg(0,
2841            "error messages in the log. Read them; analyze them; see if  ");
2842    log_msg(0,
2843            "they are significant; above all, verify your backups! Please");
2844    log_msg(0,
2845            "attach a compressed copy of this log to any e-mail you send ");
2846    log_msg(0,
2847            "to the Mondo mailing list when you are seeking technical    ");
2848    log_msg(0,
2849            "support. Without it, we can't help you.            - DevTeam");
2850    log_msg(0,
2851            "------------------------------------------------------------");
2852    log_msg(0,
2853            "BTW, despite (or perhaps because of) the wealth of messages,");
2854    log_msg(0,
2855            "some users are inclined to stop reading this log.  If Mondo ");
2856    log_msg(0,
2857            "stopped for some reason, chances are it's detailed here.    ");
2858    log_msg(0,
2859            "More than likely there's a message at the very end of this  ");
2860    log_msg(0,
2861            "log that will tell you what is wrong.  Please read it!      ");
2862    log_msg(0,
2863            "------------------------------------------------------------");
2864}
2865
2866
2867
2868/**
2869 * Restore the user's data.
2870 * What did you think it did, anyway? :-)
2871 */
2872int main(int argc, char *argv[])
2873{
2874    FILE *fin;
2875    FILE *fout;
2876    int retval = 0;
2877    int res;
2878//  int c;
2879    char *tmp;
2880
2881    struct mountlist_itself *mountlist;
2882    struct raidlist_itself *raidlist;
2883    struct s_node *filelist;
2884    char *a, *b;
2885    bool run_postnuke = FALSE;
2886
2887  /**************************************************************************
2888   * hugo-                                                                  *
2889   * busy stuff here - it needs some comments -stan                           *
2890   *                                                                        *
2891   **************************************************************************/
2892    if (getuid() != 0) {
2893        fprintf(stderr, "Please run as root.\r\n");
2894        exit(127);
2895    }
2896
2897    g_loglevel = DEFAULT_MR_LOGLEVEL;
2898    malloc_string(tmp);
2899
2900/* Configure global variables */
2901#ifdef __FreeBSD__
2902    if (strstr
2903        (call_program_and_get_last_line_of_output("cat /tmp/cmdline"),
2904         "textonly"))
2905#else
2906    if (strstr
2907        (call_program_and_get_last_line_of_output("cat /proc/cmdline"),
2908         "textonly"))
2909#endif
2910    {
2911        g_text_mode = TRUE;
2912        log_msg(1, "TEXTONLY MODE");
2913    } else {
2914        g_text_mode = FALSE;
2915    }                           // newt :-)
2916    if (!
2917        (bkpinfo = g_bkpinfo_DONTUSETHIS =
2918         malloc(sizeof(struct s_bkpinfo)))) {
2919        fatal_error("Cannot malloc bkpinfo");
2920    }
2921    if (!(mountlist = malloc(sizeof(struct mountlist_itself)))) {
2922        fatal_error("Cannot malloc mountlist");
2923    }
2924    if (!(raidlist = malloc(sizeof(struct raidlist_itself)))) {
2925        fatal_error("Cannot malloc raidlist");
2926    }
2927
2928    malloc_libmondo_global_strings();
2929
2930    strcpy(g_mondo_home,
2931           call_program_and_get_last_line_of_output("which mondorestore"));
2932    sprintf(g_tmpfs_mountpt, "/tmp/tmpfs");
2933    make_hole_for_dir(g_tmpfs_mountpt);
2934    g_current_media_number = 1; // precaution
2935
2936    run_program_and_log_output("mkdir -p " MNT_CDROM, FALSE);
2937    run_program_and_log_output("mkdir -p /mnt/floppy", FALSE);
2938
2939    malloc_string(tmp);
2940    malloc_string(a);
2941    malloc_string(b);
2942    setup_MR_global_filenames();    // malloc() and set globals, using bkpinfo->tmpdir etc.
2943    reset_bkpinfo();
2944    bkpinfo->backup_media_type = none;  // in case boot disk was made for one backup type but user wants to restore from another backup type
2945    bkpinfo->restore_data = TRUE;   // Well, yeah :-)
2946    if (am_I_in_disaster_recovery_mode()) {
2947        run_program_and_log_output("mount / -o remount,rw", 2);
2948    }                           // for b0rken distros
2949    g_main_pid = getpid();
2950    srandom((int) (time(NULL)));
2951    register_pid(getpid(), "mondo");
2952    set_signals(TRUE);
2953    g_kernel_version = get_kernel_version();
2954
2955    log_msg(1, "FYI - g_mountlist_fname = %s", g_mountlist_fname);
2956    if (strlen(g_mountlist_fname) < 3) {
2957        fatal_error
2958            ("Serious error in malloc()'ing. Could be a bug in your glibc.");
2959    }
2960    mkdir(MNT_CDROM, 0x770);
2961
2962/* Backup original mountlist.txt */
2963    sprintf(tmp, "%s.orig", g_mountlist_fname);
2964    if (!does_file_exist(g_mountlist_fname)) {
2965        log_msg(2,
2966                "%ld: Warning - g_mountlist_fname (%s) does not exist yet",
2967                __LINE__, g_mountlist_fname);
2968    } else if (!does_file_exist(tmp)) {
2969        sprintf(tmp, "cp -f %s %s.orig", g_mountlist_fname,
2970                g_mountlist_fname);
2971        run_program_and_log_output(tmp, FALSE);
2972    }
2973
2974/* Init directories */
2975    make_hole_for_dir(bkpinfo->tmpdir);
2976    sprintf(tmp, "mkdir -p %s", bkpinfo->tmpdir);
2977    run_program_and_log_output(tmp, FALSE);
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(MINDI_CACHE"/changed.files")) {
3263            log_to_screen
3264                ("See "MINDI_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.