source: branches/stable/mondo/src/mondorestore/mondorestore.c @ 1770

Last change on this file since 1770 was 1770, checked in by bruno, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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