source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondorestore.c @ 2291

Last change on this file since 2291 was 2291, checked in by Bruno Cornec, 11 years ago
  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string

(report bug fix done originaly in 2.2.9)

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