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

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 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.