source: MondoRescue/branches/3.1/mondo/src/mondorestore/mondo-rstr-tools.c

Last change on this file was 3193, checked in by Bruno Cornec, 11 years ago
  • Finish with backports from 3.1 for now. Still some work to do, but we will now make that version compile and work again and serve as a base

so the gettext patch can be added

  • Property svn:keywords set to Id
File size: 64.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 3193 2013-09-29 07:31:34Z bruno $
3***************************************************************************/
4
5#include <pthread.h>
6#include <linux/fd.h>
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "mr_str.h"
10#include "../common/mondostructures.h"
11#include "../common/libmondo.h"
12#include "mr-externs.h"
13#include "mondo-rstr-tools.h"
14
15extern bool g_ISO_restore_mode; /* are we in Iso Mode? */
16extern bool g_I_have_just_nuked;
17/*
18extern char *g_tmpfs_mountpt;
19*/
20extern char *g_isodir_device;
21extern long g_current_progress, g_maximum_progress;
22extern char *g_biggielist_pot; // list of big files which _could_ be restored, if the
23 // user chooses them
24extern char *g_filelist_imagedevs; // list of devices (e.g. /dev/hda1, /dev/sda5) which
25 // were archived as images, not just /dev entries
26 // ... e.g. NTFS, BeOS partitions
27extern char *g_imagedevs_restthese; // of the imagedevs listed in FILELIST_IMAGEDEVS,
28 // restore only these
29extern char *g_mondo_home; // homedir of Mondo; usually /usr/local/share/mondo
30
31extern t_bkptype g_backup_media_type;
32
33extern int g_partition_table_locked_up;
34extern char *MONDO_LOGFILE;
35
36/* Reference to global bkpinfo */
37extern struct s_bkpinfo *bkpinfo;
38
39/* Should we use or not extended attributes and acl when restoring */
40char *g_getfattr = NULL;
41char *g_getfacl = NULL;
42
43extern void kill_anything_like_this(char *str);
44extern int skip_obdr(void);
45extern int mount_media();
46extern int set_tape_block_size_with_mt(long internal_tape_block_size);
47
48/**
49* @addtogroup restoreUtilityGroup
50* @{
51*/
52/**
53* Free the malloc()s for the filename variables.
54*/
55void free_MR_global_filenames(void)
56{
57paranoid_free(g_filelist_imagedevs);
58paranoid_free(g_imagedevs_restthese);
59paranoid_free(g_mondo_home);
60/*
61paranoid_free(g_tmpfs_mountpt);
62*/
63mr_free(g_isodir_device);
64
65}
66
67
68
69/**
70* Ask the user which imagedevs from the list contained in @p infname should
71* actually be restored.
72* @param infname The file containing a list of all imagedevs.
73* @param outfname The location of the output file containing the imagedevs the user wanted to restore.
74* @ingroup restoreUtilityGroup
75*/
76void ask_about_these_imagedevs(char *infname, char *outfname) {
77
78FILE *fin;
79FILE *fout;
80char *incoming = NULL;
81char *question = NULL;
82
83assert_string_is_neither_NULL_nor_zerolength(infname);
84assert_string_is_neither_NULL_nor_zerolength(outfname);
85
86if (!(fin = fopen(infname, "r"))) {
87 fatal_error("Cannot openin infname");
88}
89if (!(fout = fopen(outfname, "w"))) {
90 fatal_error("Cannot openin outfname");
91}
92for (mr_getline(incoming, fin); !feof(fin) && (incoming != NULL); mr_getline(incoming, fin)) {
93 mr_strip_spaces(incoming);
94
95 if (incoming[0] == '\0') {
96 mr_free(incoming);
97 continue;
98 }
99
100 mr_asprintf(question, "Should I restore the image of %s ?", incoming);
101
102 if (ask_me_yes_or_no(question)) {
103 fprintf(fout, "%s\n", incoming);
104 }
105 mr_free(incoming);
106}
107mr_free(incoming);
108mr_free(question);
109paranoid_fclose(fout);
110paranoid_fclose(fin);
111}
112
113/**************************************************************************
114*ASK_ABOUT_THESE_IMAGEDEVS *
115**************************************************************************/
116
117/**
118* Determine whether @p list_fname contains a line containing @p f.
119* @param f The line to search for.
120* @param list_fname The file to search in.
121* @param preamble Ignore this beginning part of @p f ("" to disable).
122* @return TRUE if it's in the list, FALSE if it's not.
123*/
124bool is_file_in_list(char *f, char *list_fname, char *preamble)
125{
126
127char *command = NULL;
128char *file = NULL;
129char *tmp = NULL;
130int res;
131
132assert_string_is_neither_NULL_nor_zerolength(f);
133assert_string_is_neither_NULL_nor_zerolength(list_fname);
134assert(preamble != NULL);
135
136if (strncmp(preamble, f, strlen(preamble)) == 0) {
137 mr_asprintf(file, "%s", f + strlen(preamble));
138} else {
139 mr_asprintf(file, "%s", f);
140}
141if (file[0] == '/' && file[1] == '/') {
142 tmp = file;
143
144 mr_asprintf(file, "%s", tmp + 1);
145 mr_free(tmp);
146}
147log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
148mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
149mr_free(file);
150
151res = run_program_and_log_output(command, FALSE);
152mr_free(command);
153if (res) {
154 return (FALSE);
155} else {
156 return (TRUE);
157}
158}
159
160/**************************************************************************
161*END_IS_FILE_IN_LIST *
162**************************************************************************/
163
164
165
166/**
167* Set up an ISO backup.
168* @param bkpinfo The backup information structure. Fields used:
169* - @c bkpinfo->backup_media_type
170* - @c bkpinfo->disaster_recovery
171* - @c bkpinfo->isodir
172* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
173* @return 0 for success, nonzero for failure.
174*/
175int iso_fiddly_bits(bool nuke_me_please) {
176
177char *mount_isodir_command = NULL;
178char *command = NULL;
179char *mds = NULL;
180int retval = 0, i;
181char *isodir_format = NULL;
182
183g_ISO_restore_mode = TRUE;
184mr_free(g_isodir_device);
185g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
186if (bkpinfo->disaster_recovery) {
187 /* Patch Conor Daly 26-june-2004
188 * Don't let this clobber an existing bkpinfo->isodir */
189 if (!bkpinfo->isodir[0]) {
190 mr_free(bkpinfo->isodir);
191 mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
192 }
193 /* End patch */
194 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
195 run_program_and_log_output(command, 5);
196 mr_free(command);
197 log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
198}
199
200/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
201if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
202 mr_free(isodir_format);
203 return (1);
204}
205paranoid_system("umount -d " MNT_CDROM " 2> /dev/null"); /* just in case */
206
207if (is_this_device_mounted(g_isodir_device)) {
208 log_to_screen("WARNING - isodir is already mounted");
209} else {
210 mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
211 if (isodir_format) {
212 mr_strcat(mount_isodir_command, " -t %s", isodir_format);
213 }
214
215 mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
216 run_program_and_log_output("df -m -P", FALSE);
217 log_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command);
218 if (run_program_and_log_output(mount_isodir_command, FALSE)) {
219 popup_and_OK
220 ("Cannot mount the device where the ISO files are stored.");
221 return (1);
222 }
223 paranoid_free(mount_isodir_command);
224 log_to_screen
225 ("I have mounted the device where the ISO files are stored.");
226}
227mr_free(isodir_format);
228
229if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
230 mount_media();
231}
232i = what_number_cd_is_this(); /* has the side-effect of calling mount_media() */
233mds = media_descriptor_string(bkpinfo->backup_media_type);
234mr_free(mds);
235
236log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
237if (i < 0) {
238 popup_and_OK("Cannot find ISO images in the directory you specified.");
239 retval = 1;
240}
241log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
242return (retval);
243}
244
245
246
247
248/**
249* Kill all Petris processes.
250*/
251void kill_petris(void) {
252 kill_anything_like_this("petris");
253}
254
255/**************************************************************************
256*END_KILL_PETRIS *
257**************************************************************************/
258
259
260/**
261 * Mount @p device at @p mpt as @p format.
262 * @param device The device (/dev entry) to mount.
263 * @param mpt The directory to mount it on.
264 * @param format The filesystem type of @p device.
265 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
266 * @return 0 for success, nonzero for failure.
267 */
268int mount_device(char *device, char *mpt, char *format, bool writeable)
269{
270int res = 0;
271
272/** malloc **/
273char *tmp = NULL;
274char *command = NULL;
275char *mountdir = NULL;
276char *mountpoint = NULL;
277char *additional_parameters = NULL;
278
279assert_string_is_neither_NULL_nor_zerolength(device);
280assert_string_is_neither_NULL_nor_zerolength(mpt);
281assert(format != NULL);
282
283 if (!strcmp(mpt, "/1")) {
284 mr_asprintf(mountpoint, "/");
285 log_msg(3, "Mommm! SME is being a dildo!");
286 } else {
287 mr_asprintf(mountpoint, "%s", mpt);
288 }
289
290 if (!strcmp(mountpoint, "lvm")) {
291 return (0);
292 }
293 if (!strcmp(mountpoint, "image")) {
294 return (0);
295 }
296 mr_asprintf(tmp, "Mounting device %s ", device);
297 log_msg(1, tmp);
298 /* Deal with additional params only if not /proc or /sys */
299 mr_asprintf(additional_parameters, "");
300 if (strcmp(format, "proc") && strcmp(format, "sys")) {
301 if (writeable) {
302 mr_strcat(additional_parameters, "-o rw");
303 } else {
304 mr_strcat(additional_parameters, "-o ro");
305 }
306 mr_free(tmp);
307
308 tmp = find_home_of_exe("setfattr");
309 if (tmp) {
310 mr_strcat(additional_parameters, ",user_xattr");
311 }
312 mr_free(tmp);
313
314 tmp = find_home_of_exe("setfacl");
315 if (tmp) {
316 mr_strcat(additional_parameters, ",acl");
317 }
318 mr_free(tmp);
319 }
320
321 if (!strcmp(mountpoint, "swap")) {
322 mr_asprintf(command, "swapon %s", device);
323 mr_asprintf(mountdir, "swap");
324 } else {
325 if (!strcmp(mountpoint, "/")) {
326 mr_asprintf(mountdir, "%s", MNT_RESTORING);
327 } else {
328 mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
329 }
330 mr_asprintf(command, "mkdir -p %s", mountdir);
331 run_program_and_log_output(command, FALSE);
332 mr_free(command);
333
334 mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
335 log_msg(2, "command='%s'", command);
336 }
337 mr_free(additional_parameters);
338
339 res = run_program_and_log_output(command, TRUE);
340 if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
341 log_msg(1, "Re-trying without the fancy extra parameters");
342 mr_free(command);
343 mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
344 res = run_program_and_log_output(command, TRUE);
345 }
346 if (res) {
347 log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
348 log_msg(1, "command was '%s'", command);
349 if (!strcmp(mountpoint, "swap")) {
350 log_to_screen(tmp);
351 } else {
352 log_msg(2, "Retrying w/o the '-t' switch");
353 mr_free(command);
354 mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
355 log_msg(2, "2nd command = '%s'", command);
356 res = run_program_and_log_output(command, TRUE);
357 if (res == 0) {
358 log_msg(1,
359 "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
360 } else {
361 log_to_screen(tmp);
362 }
363 }
364 }
365
366 if (res && !strcmp(mountpoint, "swap")) {
367 log_msg(2, "That's ok. It's just a swap partition.");
368 log_msg(2, "Non-fatal error. Returning 0.");
369 res = 0;
370 }
371
372mr_free(tmp);
373mr_free(command);
374mr_free(mountdir);
375mr_free(mountpoint);
376
377return (res);
378}
379/**************************************************************************
380 *END_MOUNT_DEVICE *
381**************************************************************************/
382
383
384/**
385 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
386 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
387 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
388 * @return The number of errors encountered (0 for success).
389 */
390int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
391{
392int retval = 0, lino, res;
393char *tmp = NULL;
394char *these_failed = NULL;
395struct mountlist_itself *mountlist = NULL;
396
397assert(p_external_copy_of_mountlist != NULL);
398mountlist = malloc(sizeof(struct mountlist_itself));
399memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
400 sizeof(struct mountlist_itself));
401 sort_mountlist_by_mountpoint(mountlist, 0);
402
403
404 mvaddstr_and_log_it(g_currentY, 0, "Mounting devices ");
405 open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
406
407 mr_asprintf(these_failed, "");
408 for (lino = 0; lino < mountlist->entries; lino++) {
409 if (!strcmp(mountlist->el[lino].device, "/proc")) {
410 log_msg(1, "Again with the /proc - why is this in your mountlist?");
411 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
412 log_to_screen("%s is already mounted", mountlist->el[lino].device);
413 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
414 && strcmp(mountlist->el[lino].mountpoint, "lvm")
415 && strcmp(mountlist->el[lino].mountpoint, "raid")
416 && strcmp(mountlist->el[lino].mountpoint, "image")) {
417 mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
418 update_progress_form(tmp);
419 mr_free(tmp);
420 res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
421 retval += res;
422 if (res) {
423 mr_strcat(these_failed, "%s ",mountlist->el[lino].device);
424 }
425 }
426 g_current_progress++;
427 }
428 close_progress_form();
429 if (retval) {
430 if (g_partition_table_locked_up > 0) {
431 log_to_screen("fdisk's ictol() call to refresh its copy of the partition table causes the kernel to");
432 log_to_screen("lock up the partition table. You might have to reboot and use Interactive Mode to");
433 log_to_screen("format and restore *without* partitioning first. Sorry for the inconvenience.");
434 }
435 mr_asprintf(tmp, "Could not mount device(s) %s- shall I abort?", these_failed);
436
437 if (!ask_me_yes_or_no(tmp)) {
438 retval = 0;
439 log_to_screen("Continuing, although some device(s) failed to be mounted");
440 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
441 } else {
442 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
443 log_to_screen("Unable to mount some or all of your partitions.");
444 }
445 mr_free(tmp);
446 } else {
447 log_to_screen("All partitions were mounted OK.");
448 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
449 }
450 paranoid_free(these_failed);
451
452 /* Also mounting under MNT_RESTORING special FS */
453 (void)mount_device("/proc","/proc","proc",TRUE);
454 (void)mount_device("/sys","/sys","sysfs",TRUE);
455 run_program_and_log_output("df -m -P", 3);
456 paranoid_free(mountlist);
457 return (retval);
458}
459/**************************************************************************
460*END_MOUNT_ALL_DEVICES *
461**************************************************************************/
462
463
464/**
465* Fix some miscellaneous things in the filesystem so the system will come
466* up correctly on the first boot.
467*/
468void protect_against_braindead_sysadmins()
469{
470run_program_and_log_output("touch " MNT_RESTORING "/var/log/pacct",
471 FALSE);
472run_program_and_log_output("touch " MNT_RESTORING "/var/account/pacct",
473 FALSE);
474if (run_program_and_log_output("ls " MNT_RESTORING " /tmp", FALSE)) {
475run_program_and_log_output("chmod 1777 " MNT_RESTORING "/tmp",
476 FALSE);
477}
478run_program_and_log_output("mkdir -p " MNT_RESTORING
479 "/var/run/console", FALSE);
480run_program_and_log_output("chmod 777 " MNT_RESTORING "/dev/null",
481 FALSE);
482run_program_and_log_output("cd " MNT_RESTORING
483 "; for i in `ls home/`; do echo \"Moving $i's spurious files to $i/.disabled\"; mkdir \"$i\"/.disabled ; mv -f \"$i\"/.DCOP* \"$i\"/.MCOP* \"$i\"/.*authority \"$i\"/.kde/tmp* \"$i\"/.kde/socket* \"$i\"/.disabled/ ; done",
484 TRUE);
485run_program_and_log_output("rm -f " MNT_RESTORING "/var/run/*.pid",
486 TRUE);
487run_program_and_log_output("rm -f " MNT_RESTORING "/var/lock/subsys/*",
488 TRUE);
489}
490
491/**************************************************************************
492*END_PROTECT_AGAINST_BRAINDEAD_SYSADMINS *
493**************************************************************************/
494
495
496/**
497 * Extract mondorestore.cfg and the mountlist from the tape inserted
498 * to the ./tmp/ directory.
499 * @param dev The tape device to read from.
500 * @return 0 for success, nonzero for failure.
501 */
502int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
503{
504 char *command = NULL;
505 int res = 0;
506
507 if (bkpinfo->use_obdr) {
508 skip_obdr();
509 } else {
510 // BCO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
511 set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
512 }
513
514 mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size);
515 log_msg(2, "command = '%s'", command);
516 res = run_program_and_log_output(command, -1);
517 mr_free(command);
518
519 return (res);
520}
521
522
523
524/**
525 * Get the configuration file from the initrd of the backup media
526 * case when calling mondorestore live
527 * @param bkpinfo The backup information structure. Fields used:
528 * - @c bkpinfo->backup_media_type
529 * - @c bkpinfo->media_device
530 * - @c bkpinfo->tmpdir
531 * @return 0 for success, nonzero for failure.
532 */
533void get_cfg_file_from_initrd()
534{
535 /** malloc *****/
536 char *command = NULL;
537 char *cfg_file = NULL;
538 char *tmp = NULL;
539 char *mountpt = NULL;
540
541 bool try_plan_B;
542
543 assert(bkpinfo != NULL);
544 log_msg(2, "gcffa --- starting");
545 log_to_screen("I'm thinking...");
546 mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
547 mr_asprintf(command, "mkdir -p %s", mountpt);
548 run_program_and_log_output(command, FALSE);
549 log_msg(2, "mountpt = %s; ", mountpt);
550 mr_free(command);
551
552 if (chdir(bkpinfo->tmpdir)) {
553 //FIXME
554 }
555
556 mr_free(mountpt);
557
558 if (!does_file_exist(cfg_file)) {
559 log_msg(2, "gcffa --- we don't have cfg file yet.");
560 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
561 try_plan_B = TRUE;
562 } else {
563 log_msg(2, "gcffa --- calling mount_media now :)");
564 if (!mount_media()) {
565 log_msg(2,
566 "gcffa --- managed to mount CD; so, no need for Plan B");
567 try_plan_B = FALSE;
568 } else {
569 try_plan_B = TRUE;
570 }
571 if (what_number_cd_is_this() > 1) {
572 insist_on_this_cd_number((g_current_media_number = 1));
573 }
574 }
575 if (try_plan_B) {
576 log_msg(2, "gcffa --- OK, switching to Plan B");
577 if (chdir(bkpinfo->tmpdir)) {
578 // FIXME
579 }
580 run_program_and_log_output("mkdir -p tmp", FALSE);
581
582 if (! bkpinfo->media_device) {
583 mr_asprintf(bkpinfo->media_device, "/dev/st0");
584 log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device);
585 }
586 mr_asprintf(tmp, "%s", bkpinfo->media_device);
587 if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
588 mr_free(bkpinfo->media_device);
589 mr_asprintf(bkpinfo->media_device, "/dev/st0");
590 if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
591 mr_free(bkpinfo->media_device);
592 mr_asprintf(bkpinfo->media_device, "/dev/osst0");
593 if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
594 mr_free(bkpinfo->media_device);
595 mr_asprintf(bkpinfo->media_device, "/dev/ht0");
596 if (extract_cfg_file_and_mountlist_from_tape_dev (bkpinfo->media_device)) {
597 log_msg(3, "I tried lots of devices but none worked.");
598 mr_free(bkpinfo->media_device);
599 mr_asprintf(bkpinfo->media_device, "%s", tmp);
600 }
601 }
602 }
603 }
604 mr_free(tmp);
605
606 if (!does_file_exist(MINDI_CACHE_REL"/mondorestore.cfg")) {
607 log_to_screen("Cannot find config info on media");
608 }
609 } else {
610 log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
611 mr_asprintf(command, "tar -zxvf "MNT_CDROM"/images/all.tar.gz ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm"); // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
612 run_program_and_log_output(command, TRUE);
613 mr_free(command);
614 }
615 }
616 run_program_and_log_output("umount -d "MNT_CDROM, FALSE);
617 if (!does_file_exist(cfg_file)) {
618 log_it("%s",cfg_file);
619 log_msg(1, "%s not found", cfg_file);
620 log_to_screen("Oh dear. Unable to recover configuration file from boot disk");
621 }
622
623 log_to_screen("Recovered mondorestore.cfg");
624
625 run_program_and_log_output(command, FALSE);
626 mr_free(command);
627
628 mr_asprintf(command, "cp -f etc/raidtab /etc/");
629 run_program_and_log_output(command, FALSE);
630 mr_free(command);
631
632 g_backup_media_type = bkpinfo->backup_media_type;
633}
634
635
636
637/**
638* Fill out @p bkpinfo based on @p cfg_file.
639* @param cfg_file The mondorestore.cfg file to read into @p bkpinfo.
640* @param bkpinfo The backup information structure to fill out with information
641* from @p cfg_file.
642* @return 0 for success, nonzero for failure.
643*/
644int read_cfg_file_into_bkpinfo(char *cfgf)
645{
646/** add mallocs **/
647char *value = NULL;
648char *tmp = NULL;
649char *tmp1 = NULL;
650char *envtmp1 = NULL;
651char *envtmp2 = NULL;
652char *command = NULL;
653char *iso_mnt = NULL;
654char *iso_path = NULL;
655char *old_isodir = NULL;
656char *cfg_file = NULL;
657t_bkptype media_specified_by_user;
658
659// assert_string_is_neither_NULL_nor_zerolength(cfg_file);
660assert(bkpinfo != NULL);
661assert(cfgf != NULL);
662log_it("Entering read_cfg_file_into_bkpinfo");
663
664media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
665
666if ((value = read_cfg_var(cfg_file, "backup-media-type")) != NULL) {
667 if (!strcmp(value, "cdstream")) {
668 bkpinfo->backup_media_type = cdstream;
669 } else if (!strcmp(value, "cdr")) {
670 bkpinfo->backup_media_type = cdr;
671 } else if (!strcmp(value, "cdrw")) {
672 bkpinfo->backup_media_type = cdrw;
673 } else if (!strcmp(value, "dvd")) {
674 bkpinfo->backup_media_type = dvd;
675 } else if (!strcmp(value, "usb")) {
676 bkpinfo->backup_media_type = usb;
677 bkpinfo->please_dont_eject = TRUE;
678 } else if (!strcmp(value, "iso")) {
679 bkpinfo->backup_media_type = iso;
680 if (am_I_in_disaster_recovery_mode()) {
681 /* Check to see if CD is already mounted before mounting it... */
682 if (!is_this_device_mounted("/dev/cdrom")) {
683 log_msg(2, "NB: CDROM device not mounted, mounting...");
684 run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
685 }
686 if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
687 bkpinfo->backup_media_type = cdr;
688 run_program_and_log_output("umount -d "MNT_CDROM, 1);
689 log_it("Re-jigging configuration AGAIN. CD-R, not ISO.");
690 }
691 }
692 mr_free(bkpinfo->prefix);
693 mr_free(value);
694 if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
695 mr_asprintf(bkpinfo->prefix, "%s", value);
696 } else {
697 mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
698 }
699 log_it("Setting Prefix to %s", bkpinfo->prefix);
700 } else if ((!strcmp(value, "netfs")) || (!strcmp(value, "nfs"))) {
701 /* Stay compatible with previous versions by allowing nfs as an entry here */
702 bkpinfo->backup_media_type = netfs;
703 bkpinfo->please_dont_eject = TRUE;
704 mr_free(value);
705
706 mr_free(bkpinfo->netfs_user);
707 if ((value = read_cfg_var(cfg_file, "netfs-server-user")) == 0) {
708 mr_asprintf(bkpinfo->netfs_user,"%s", value);
709 }
710
711 mr_free(bkpinfo->netfs_proto);
712 if ((value = read_cfg_var(cfg_file, "netfs-proto")) == 0) {
713 mr_asprintf(bkpinfo->netfs_proto, "%s", value);
714 } else {
715 /* For compatibility, force protocol in old nfs case to be transparent */
716 mr_asprintf(bkpinfo->netfs_proto, "nfs");
717 }
718 mr_free(value);
719
720 mr_free(bkpinfo->prefix);
721 if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
722 mr_asprintf(bkpinfo->prefix,"%s", value);
723 } else {
724 mr_asprintf(bkpinfo->prefix,"%s", STD_PREFIX);
725 }
726
727 tmp = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
728 if (strstr(tmp, "pxe")) {
729 /* We need to override prefix value in PXE mode as it's
730 * already done in start-netfs */
731 envtmp1 = getenv("imgname");
732 if (envtmp1 == NULL) {
733 fatal_error("no imgname variable in environment");
734 }
735 mr_free(bkpinfo->prefix);
736 mr_asprintf(bkpinfo->prefix, "%s", envtmp1);
737 }
738 mr_free(tmp);
739
740 } else if (!strcmp(value, "tape")) {
741 bkpinfo->backup_media_type = tape;
742 } else if (!strcmp(value, "udev")) {
743 bkpinfo->backup_media_type = udev;
744 } else {
745 fatal_error("UNKNOWN bkp-media-type");
746 }
747} else {
748 fatal_error("backup-media-type not specified!");
749}
750mr_free(value);
751
752if (bkpinfo->disaster_recovery) {
753 if (bkpinfo->backup_media_type == cdstream) {
754 mr_free(bkpinfo->media_device);
755 mr_asprintf(bkpinfo->media_device, "/dev/cdrom");
756 bkpinfo->media_size = 650; /* good guess */
757 } else if (bkpinfo->backup_media_type == usb) {
758 envtmp1 = getenv("MRUSBDEV");
759 if (envtmp1 == NULL) {
760 if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
761 fatal_error("Cannot get USB device name from cfg file");
762 }
763 } else {
764 mr_asprintf(value,"%s", envtmp1);
765 }
766 mr_free(bkpinfo->media_device);
767 mr_asprintf(bkpinfo->media_device, "%s1", value);
768 mr_free(value);
769 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
770 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
771 if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
772 fatal_error("Cannot get tape device name from cfg file");
773 }
774 mr_free(bkpinfo->media_device);
775 bkpinfo->media_device = value;
776
777 value = read_cfg_var(cfg_file, "media-size");
778 if (value != NULL) {
779 bkpinfo->media_size = atol(value);
780 mr_free(value);
781 } else {
782 bkpinfo->media_size = 0L;
783 }
784 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
785 } else {
786 mr_free(bkpinfo->media_device);
787 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
788 bkpinfo->media_size = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
789 log_msg(2, "Backup medium is similar to CD-R[W]");
790 }
791} else {
792 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
793}
794
795value = read_cfg_var(cfg_file, "use-star");
796if (value && strstr(value, "yes")) {
797 bkpinfo->use_star = TRUE;
798 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
799}
800mr_free(value);
801
802value = read_cfg_var(cfg_file, "obdr");
803if (value && strstr(value, "TRUE")) {
804 bkpinfo->use_obdr = TRUE;
805 log_msg(1, "OBDR mode activated");
806}
807mr_free(value);
808
809value = read_cfg_var(cfg_file, "acl");
810if (value && strstr(value, "TRUE")) {
811 mr_asprintf(g_getfacl,"setfacl");
812 log_msg(1, "We will restore ACLs");
813 tmp = find_home_of_exe("setfacl");
814 if (!tmp) {
815 log_msg(1, "Unable to restore ACLs as no setfacl found");
816 }
817 mr_free(tmp);
818}
819mr_free(value);
820
821value = read_cfg_var(cfg_file, "xattr");
822if (value && strstr(value, "TRUE")) {
823 mr_asprintf(g_getfattr,"setfattr");
824 log_msg(1, "We will restore XATTRs");
825 tmp = find_home_of_exe("setfattr");
826 if (!tmp) {
827 log_msg(1, "Unable to restore XATTRs as no setfattr found");
828 }
829 mr_free(tmp);
830}
831mr_free(value);
832
833value = read_cfg_var(cfg_file, "internal-tape-block-size");
834if (value != NULL) {
835 bkpinfo->internal_tape_block_size = atol(value);
836} else {
837 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
838}
839log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
840mr_free(value);
841
842value = read_cfg_var(cfg_file, "use-lzma");
843if (value && strstr(value, "yes")) {
844 bkpinfo->use_lzma = TRUE;
845 bkpinfo->use_lzo = FALSE;
846 bkpinfo->use_gzip = FALSE;
847 mr_free(bkpinfo->zip_exe);
848 mr_asprintf(bkpinfo->zip_exe, "lzma");
849 mr_free(bkpinfo->zip_suffix);
850 mr_asprintf(bkpinfo->zip_suffix, "lzma");
851}
852mr_free(value);
853
854value = read_cfg_var(cfg_file, "use-lzo");
855if (value && strstr(value, "yes")) {
856 bkpinfo->use_lzma = FALSE;
857 bkpinfo->use_lzo = TRUE;
858 bkpinfo->use_gzip = FALSE;
859 mr_free(bkpinfo->zip_exe);
860 mr_asprintf(bkpinfo->zip_exe, "lzop");
861 mr_free(bkpinfo->zip_suffix);
862 mr_asprintf(bkpinfo->zip_suffix, "lzo");
863}
864mr_free(value);
865
866value = read_cfg_var(cfg_file, "use-gzip");
867if (value && strstr(value, "yes")) {
868 bkpinfo->use_lzma = FALSE;
869 bkpinfo->use_lzo = FALSE;
870 bkpinfo->use_gzip = TRUE;
871 mr_free(bkpinfo->zip_exe);
872 mr_asprintf(bkpinfo->zip_exe, "gzip");
873 mr_free(bkpinfo->zip_suffix);
874 mr_asprintf(bkpinfo->zip_suffix, "gz");
875}
876mr_free(value);
877
878value = read_cfg_var(cfg_file, "use-comp");
879if (value && strstr(value, "yes")) {
880 bkpinfo->use_lzma = FALSE;
881 bkpinfo->use_lzo = FALSE;
882 bkpinfo->use_gzip = FALSE;
883 mr_free(bkpinfo->zip_exe);
884 mr_asprintf(bkpinfo->zip_exe, "bzip2");
885 mr_free(bkpinfo->zip_suffix);
886 mr_asprintf(bkpinfo->zip_suffix, "bz2");
887}
888mr_free(value);
889
890if (bkpinfo->zip_exe == NULL) {
891 mr_asprintf(bkpinfo->zip_exe, "none");
892}
893if (bkpinfo->zip_suffix == NULL) {
894 mr_asprintf(bkpinfo->zip_suffix, "");
895}
896
897value = read_cfg_var(cfg_file, "differential");
898if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
899 bkpinfo->differential = TRUE;
900}
901log_msg(2, "differential var = '%s'", value);
902mr_free(value);
903if (bkpinfo->differential) {
904 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
905} else {
906 log_msg(2, "This is a regular (full) backup");
907}
908
909tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
910tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
911if (tmp || strstr(tmp1, "donteject")) {
912 bkpinfo->please_dont_eject = TRUE;
913 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
914}
915mr_free(tmp);
916mr_free(tmp1);
917
918if (bkpinfo->backup_media_type == netfs) {
919 if (!cfgf) {
920 if (bkpinfo->netfs_mount) {
921 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
922 }
923 if (bkpinfo->netfs_remote_dir) {
924 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
925 }
926 log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
927 } else {
928 mr_free(bkpinfo->netfs_mount);
929 bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
930
931 mr_free(bkpinfo->netfs_remote_dir);
932 bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
933
934 if (bkpinfo->netfs_mount != NULL) {
935 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
936 }
937 if (bkpinfo->netfs_remote_dir != NULL) {
938 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
939 }
940 if (bkpinfo->netfs_proto != NULL) {
941 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
942 }
943 if (bkpinfo->netfs_user != NULL) {
944 log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
945 }
946 }
947 tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
948 if (strstr(tmp1, "pxe")) {
949 mr_free(tmp1);
950 /* We need to override values in PXE mode as it's
951 * already done in start-netfs */
952 envtmp1 = getenv("netfsmount");
953 if (envtmp1 == NULL) {
954 fatal_error("no netfsmount variable in environment");
955 }
956 envtmp2 = getenv("dirimg");
957 if (envtmp2 == NULL) {
958 fatal_error("no dirimg variable in environment");
959 }
960 mr_free(bkpinfo->netfs_mount);
961 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
962
963 mr_free(bkpinfo->netfs_remote_dir);
964 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
965 } else {
966 mr_free(tmp1);
967 }
968} else if (bkpinfo->backup_media_type == iso) {
969 /* Patch by Conor Daly 23-june-2004
970 * to correctly mount iso-dev and set a sensible
971 * isodir in disaster recovery mode
972 */
973 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
974 iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
975 iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
976 mr_free(bkpinfo->isodir);
977 mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
978 mr_free(iso_mnt);
979
980 if (!bkpinfo->isodir[0]) {
981 mr_free(bkpinfo->isodir);
982 bkpinfo->isodir = old_isodir;
983 } else {
984 mr_free(old_isodir);
985 }
986 if (!bkpinfo->disaster_recovery) {
987 if (strcmp(old_isodir, bkpinfo->isodir)) {
988 log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
989 mr_free(bkpinfo->isodir);
990 bkpinfo->isodir = old_isodir;
991 } else {
992 mr_free(old_isodir);
993 }
994 }
995 mr_free(g_isodir_device);
996 g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
997 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
998
999 if (bkpinfo->disaster_recovery) {
1000 if (is_this_device_mounted(g_isodir_device)) {
1001 log_msg(2, "NB: isodir is already mounted");
1002 /* Find out where it's mounted */
1003 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
1004 log_it("command = %s", command);
1005 iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
1006 log_it("res of it = %s", iso_mnt);
1007 mr_free(command);
1008 } else {
1009 mr_asprintf(iso_mnt, "/tmp/isodir");
1010 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
1011 run_program_and_log_output(tmp1, 5);
1012 mr_free(tmp1);
1013
1014 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
1015 if (run_program_and_log_output(tmp1, 3)) {
1016 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
1017 bkpinfo->backup_media_type = cdr;
1018 mr_free(bkpinfo->media_device);
1019 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
1020 if (mount_media()) {
1021 mr_free(tmp1);
1022 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
1023 } else {
1024 log_msg(1, "You backed up to disk, then burned some CDs.");
1025 }
1026 }
1027 mr_free(tmp1);
1028 }
1029 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1030 if (bkpinfo->backup_media_type == iso) {
1031 mr_free(bkpinfo->isodir);
1032 mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1033 bkpinfo->isodir = tmp1;
1034 }
1035 mr_free(iso_mnt);
1036 }
1037 mr_free(iso_path);
1038}
1039
1040if (media_specified_by_user != none) {
1041 if (! bkpinfo->disaster_recovery) {
1042 if (bkpinfo->backup_media_type != media_specified_by_user) {
1043 log_msg(2, "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1044 interactively_obtain_media_parameters_from_user(FALSE);
1045 media_specified_by_user = bkpinfo->backup_media_type;
1046 get_cfg_file_from_initrd();
1047 }
1048 }
1049 bkpinfo->backup_media_type = media_specified_by_user;
1050}
1051g_backup_media_type = bkpinfo->backup_media_type;
1052paranoid_free(value);
1053return (0);
1054
1055}
1056
1057/**************************************************************************
1058*END_READ_CFG_FILE_INTO_BKPINFO *
1059**************************************************************************/
1060
1061
1062
1063
1064/**
1065 * Allow the user to edit the filelist and biggielist.
1066 * The filelist is unlinked after it is read.
1067 * @param bkpinfo The backup information structure. Fields used:
1068 * - @c bkpinfo->backup_media_type
1069 * - @c bkpinfo->isodir
1070 * - @c bkpinfo->media_device
1071 * - @c bkpinfo->tmpdir
1072 * @return The filelist structure containing the information read from disk.
1073 */
1074struct
1075s_node *process_filelist_and_biggielist()
1076{
1077struct s_node *filelist;
1078
1079char *command = NULL;
1080char *tmp;
1081char *q;
1082int res = 0;
1083pid_t pid;
1084bool extract_mountlist_stub = FALSE;
1085
1086assert(bkpinfo != NULL);
1087malloc_string(tmp);
1088
1089 if (getcwd(tmp, MAX_STR_LEN) == NULL) {
1090 // FIXME
1091 }
1092 if (chdir(bkpinfo->tmpdir)) {
1093 // FIXME
1094 }
1095 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1096 log_to_screen("Extracting filelist and biggielist from media...");
1097 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1098 mr_asprintf(command, "tar -b %ld -zxf %s ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm", bkpinfo->internal_tape_block_size, bkpinfo->media_device);
1099 log_msg(1, "tarcommand = %s", command);
1100 run_program_and_log_output(command, 1);
1101 mr_free(command);
1102
1103 } else {
1104 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1105 insist_on_this_cd_number(1);
1106 log_msg(2, "Back from iotcn");
1107 run_program_and_log_output("mount", 1);
1108 mr_asprintf(command, "tar -zxf "MNT_CDROM"/images/all.tar.gz ."MINDI_CACHE"/biggielist.txt ."MINDI_CACHE"/filelist.full.gz ."MINDI_CACHE"/i-want-my-lvm");
1109
1110 log_msg(1, "tarcommand = %s", command);
1111 run_program_and_log_output(command, 1);
1112 mr_free(command);
1113
1114 if (!does_file_exist(MINDI_CACHE"/biggielist.txt")) {
1115 fatal_error("all.tar.gz did not include "MINDI_CACHE"/biggielist.txt");
1116 }
1117 if (!does_file_exist(MINDI_CACHE"/filelist.full.gz")) {
1118 fatal_error("all.tar.gz did not include "MINDI_CACHE"/filelist.full.gz");
1119 }
1120 }
1121 if (chdir(tmp)) {
1122 // FIXME
1123 }
1124
1125 log_msg(2, "Forking");
1126 pid = fork();
1127 switch (pid) {
1128 case -1:
1129 fatal_error("Forking error");
1130 break;
1131
1132 case 0:
1133 log_to_screen("Pre-processing filelist");
1134 mr_asprintf(command, "grep -E '^/dev/.*' "MINDI_CACHE"/biggielist.txt > %s 2> /dev/null", g_filelist_imagedevs);
1135 paranoid_system(command);
1136 mr_free(command);
1137 exit(0);
1138 break;
1139
1140 default:
1141 open_evalcall_form("Pre-processing filelist");
1142 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1143 usleep(100000);
1144 update_evalcall_form(0);
1145 }
1146 }
1147 close_evalcall_form();
1148
1149 log_msg(3, "loading filelist");
1150 filelist = load_filelist(MINDI_CACHE"/filelist.full.gz");
1151 log_msg(3, "deleting original filelist");
1152 unlink(MINDI_CACHE"/filelist.full.gz");
1153 if (g_text_mode) {
1154 q = NULL;
1155 while (q == NULL) {
1156 printf("Restore which directory? --> ");
1157 mr_getline(q, stdin);
1158 }
1159 toggle_path_selection(filelist, q, TRUE);
1160 if (strlen(q) == 0) {
1161 res = 1;
1162 } else {
1163 res = 0;
1164 }
1165 mr_free(q);
1166 } else {
1167 res = edit_filelist(filelist);
1168 }
1169 if (res) {
1170 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1171 free_filelist(filelist);
1172 return (NULL);
1173 }
1174 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1175 close_evalcall_form();
1176
1177 // NB: It's not necessary to add biggielist.txt to the filelist.full
1178 // file. The filelist.full file already contains the filename of EVERY
1179 // file backed up - regular and biggie files.
1180
1181 // However, we do want to make sure the imagedevs selected by the user
1182 // are flagged for restoring.
1183 if (length_of_file(g_imagedevs_restthese) > 2) {
1184 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1185 TRUE);
1186 }
1187
1188 paranoid_free(tmp);
1189 return (filelist);
1190}
1191
1192/**************************************************************************
1193 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1194 **************************************************************************/
1195
1196
1197
1198
1199/**
1200 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1201 * The backup filename is the filename of the original with ".pristine" added.
1202 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1203 * @param filename The filename (absolute path) within @p path_root.
1204 * @return 0 for success, nonzero for failure.
1205 */
1206int backup_crucial_file(char *path_root, char *filename)
1207{
1208 char *tmp = NULL;
1209 char *command = NULL;
1210 int res;
1211
1212 assert(path_root != NULL);
1213 assert_string_is_neither_NULL_nor_zerolength(filename);
1214
1215 mr_asprintf(tmp, "%s/%s", path_root, filename);
1216 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1217 mr_free(tmp);
1218
1219 res = run_program_and_log_output(command, 5);
1220 mr_free(command);
1221 return (res);
1222}
1223
1224void offer_to_make_initrd() {
1225
1226if (bkpinfo->restore_mode != nuke) {
1227 if (ask_me_yes_or_no
1228 ("You will now be able to re-generate your initrd.\nThis is especially useful if you changed of hardware configuration, cloned, made P2V, used multipath...\nDo you need to do it ?")) {
1229 log_msg(1,"Launching shell for manual initrd recreation");
1230 if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1231 popup_and_OK("You'll now be chrooted under your future / partition.\nEdit /etc/mkinitcpio.conf if needed and rebuild your initrd with the kernel preset name e.g.\nmkinitcpio -p kernel26\nThen type exit to finish.\n");
1232 } else {
1233 popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your init(rd|ramfs) with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nor initramfs, dracut, ... Then type exit to finish.");
1234 }
1235 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1236 if (!g_text_mode) {
1237 newtSuspend();
1238 }
1239 paranoid_system("chroot " MNT_RESTORING);
1240 if (!g_text_mode) {
1241 newtResume();
1242 }
1243 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1244 } else {
1245 return;
1246 }
1247} else {
1248 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1249 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1250}
1251}
1252
1253
1254/**
1255 * Install the user's boot loader in the MBR.
1256 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1257 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1258 * @return 0 for success, nonzero for failure.
1259 */
1260int run_boot_loader(bool offer_to_hack_scripts)
1261{
1262 int res;
1263 int retval = 0;
1264
1265 /** malloc *******/
1266 char *device = NULL;
1267 char *name = NULL;
1268 char *cmd = NULL;
1269
1270 /* In order to have a working bootloader, we need to have all devices
1271 * ready in the chroot. If they are not there (udev) then copy them from
1272 * the current /dev location
1273 */
1274 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1275 run_program_and_log_output(cmd, 3);
1276 paranoid_free(cmd);
1277
1278 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1279 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1280 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1281 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
1282 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1283 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1284 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1285 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
1286 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1287 device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.device");
1288 name = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.name");
1289 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1290 sync();
1291
1292 offer_to_make_initrd();
1293 if (!strcmp(name, "LILO")) {
1294 res = run_lilo(offer_to_hack_scripts);
1295 } else if (!strcmp(name, "ELILO")) {
1296 res = run_elilo(offer_to_hack_scripts);
1297 } else if (!strcmp(name, "GRUB")) {
1298 res = run_grub(offer_to_hack_scripts, device);
1299 } else if (!strcmp(name, "RAW")) {
1300 res = run_raw_mbr(offer_to_hack_scripts, device);
1301 }
1302#ifdef __FreeBSD__
1303 else if (!strcmp(name, "BOOT0")) {
1304 mr_asprintf(tmp, "boot0cfg -B %s", device);
1305 res = run_program_and_log_output(tmp, FALSE);
1306 paranoid_free(tmp);
1307 } else {
1308 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1309 if (!system(tmp)) {
1310 mr_free(tmp);
1311 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1312 res = run_program_and_log_output(tmp, 3);
1313 } else {
1314 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1315 }
1316 mr_free(tmp);
1317 }
1318#else
1319 else {
1320 log_to_screen
1321 ("Unable to determine type of boot loader. Defaulting to LILO.");
1322 res = run_lilo(offer_to_hack_scripts);
1323 }
1324#endif
1325 mr_free(device);
1326 mr_free(name);
1327
1328 retval += res;
1329 if (res) {
1330 log_to_screen("Your boot loader returned an error");
1331 } else {
1332 log_to_screen("Your boot loader ran OK");
1333 }
1334 return (retval);
1335}
1336
1337/**************************************************************************
1338 *END_ RUN_BOOT_LOADER *
1339 **************************************************************************/
1340
1341
1342
1343/**
1344 * Attempt to find the user's editor.
1345 * @return The editor found ("vi" if none could be found).
1346 * @note The returned string points to static storage that will be overwritten with each call.
1347 */
1348char *find_my_editor(void) {
1349
1350 char *tmp = NULL;
1351 static char output[MAX_STR_LEN];
1352
1353 tmp = find_home_of_exe("pico");
1354 if (tmp) {
1355 strcpy(output, "pico");
1356 } else {
1357 mr_free(tmp);
1358 tmp = find_home_of_exe("nano");
1359 if (tmp) {
1360 strcpy(output, "nano");
1361 } else {
1362 mr_free(tmp);
1363 tmp = find_home_of_exe("joe");
1364 if (tmp) {
1365 strcpy(output, "joe");
1366 } else {
1367 strcpy(output, "vi");
1368 }
1369 }
1370 }
1371 mr_free(tmp);
1372
1373 tmp = find_home_of_exe(output);
1374 if (!tmp) {
1375 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1376 }
1377 mr_free(tmp);
1378 return (output);
1379}
1380
1381
1382/**
1383 * Install GRUB on @p bd.
1384 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1385 * @param bd The boot device where GRUB is installed.
1386 * @return 0 for success, nonzero for failure.
1387 */
1388int run_grub(bool offer_to_run_stabgrub, char *bd)
1389{
1390 /** malloc **/
1391 char *command = NULL;
1392 char *boot_device = NULL;
1393 char *tmp = NULL;
1394 char *editor = NULL;
1395 char *p = NULL;
1396
1397 bool done;
1398 int res = 0; /* FALSE */
1399 bool mntlistchg = FALSE;
1400 FILE *fin = NULL;
1401
1402 assert_string_is_neither_NULL_nor_zerolength(bd);
1403 mr_asprintf(boot_device, "%s", bd);
1404
1405 if (offer_to_run_stabgrub
1406 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1407 /* interactive mode */
1408 mvaddstr_and_log_it(g_currentY,
1409 0,
1410 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1411 /* Did we changed the mountlist ? If yes, then force editing conf files */
1412 if ((fin = fopen(MONDO_MNTLISTCHG, "r")) != NULL) {
1413 mntlistchg = TRUE;
1414 }
1415 for (done = FALSE; !done;) {
1416 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1417 if (p == NULL) {
1418 done = TRUE;
1419 mr_free(p);
1420 /* we want some warnings later on */
1421 res = 1;
1422 continue;
1423 }
1424 /* Only try to adapt grub here first if the mountlist wasn't changed before */
1425 if (! mntlistchg) {
1426 mr_asprintf(command, "stabgrub-me %s", p);
1427 mr_free(p);
1428
1429 res = run_program_and_log_output(command, 1);
1430 mr_free(command);
1431 }
1432
1433 if ((res) || (mntlistchg)) {
1434 if (res) {
1435 popup_and_OK("GRUB installation failed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1436 } else {
1437 popup_and_OK("The mountlist was changed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
1438 }
1439 if (!g_text_mode) {
1440 newtSuspend();
1441 }
1442 mr_asprintf(editor, "%s", find_my_editor());
1443 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1444 paranoid_system(tmp);
1445 mr_free(tmp);
1446
1447 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1448 paranoid_system(tmp);
1449 mr_free(tmp);
1450
1451 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1452 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1453 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1454 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1455 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1456 mr_asprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1457 }
1458 paranoid_system(tmp);
1459 mr_free(tmp);
1460
1461 if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1462 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1463 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1464 mr_asprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1465 }
1466 paranoid_system(tmp);
1467 mr_free(tmp);
1468
1469 if (!g_text_mode) {
1470 newtResume();
1471 }
1472 mr_asprintf(command, "stabgrub-me %s", boot_device);
1473 res = run_program_and_log_output(command, 1);
1474 mr_free(command);
1475
1476 if (res) {
1477 popup_and_OK("GRUB installation failed. Please fix the conf files so that a manual install using 'grub-install' or similar command works. You are now chroot()'ed to your restored system. Please type 'exit' when you are done.");
1478 newtSuspend();
1479 paranoid_system("chroot " MNT_RESTORING);
1480 newtResume();
1481 popup_and_OK("Thank you.");
1482 } else {
1483 popup_and_OK("GRUB is now installed correctly");
1484 done = TRUE;
1485 }
1486 popup_and_OK("You will now edit fstab, mtab, device.map and menu.lst/grub.cfg");
1487 if (!g_text_mode) {
1488 newtSuspend();
1489 }
1490
1491 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1492 paranoid_system(tmp);
1493 mr_free(tmp);
1494
1495 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1496 paranoid_system(tmp);
1497 mr_free(tmp);
1498
1499 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1500 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1501 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1502 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1503 }
1504 paranoid_system(tmp);
1505 mr_free(tmp);
1506
1507 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1508 paranoid_system(tmp);
1509 mr_free(tmp);
1510 mr_free(editor);
1511
1512 if (!g_text_mode) {
1513 newtResume();
1514 }
1515 }
1516 }
1517 } else {
1518 /* nuke mode */
1519 if (!run_program_and_log_output("which grub-MR", FALSE)) {
1520 log_msg(1, "Yay! grub-MR found...");
1521 mr_asprintf(command, "grub-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1522 log_msg(1, "command = %s", command);
1523 } else {
1524 mr_asprintf(command, "chroot " MNT_RESTORING " grub-install %s", boot_device);
1525 log_msg(1, "WARNING - grub-MR not found; using grub-install");
1526 }
1527 mvaddstr_and_log_it(g_currentY, 0, "Running GRUB... ");
1528 log_it("%s",command);
1529 res = run_program_and_log_output(command, 1);
1530 mr_free(command);
1531
1532 if (res) {
1533 popup_and_OK
1534 ("Because of bugs in GRUB's own installer, GRUB was not installed properly. Please install the boot loader manually now, using this chroot()'ed shell prompt. Type 'exit' when you have finished.");
1535 newtSuspend();
1536 paranoid_system("chroot " MNT_RESTORING);
1537 newtResume();
1538 popup_and_OK("Thank you.");
1539 }
1540 }
1541 mr_free(boot_device);
1542
1543 if (res) {
1544 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1545 log_to_screen
1546 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1547 log_msg(1, "Type:-");
1548 log_msg(1, " mount-me");
1549 log_msg(1, " chroot " MNT_RESTORING);
1550 log_msg(1, " mount /boot");
1551 log_msg(1, " grub-install '(hd0)'");
1552 log_msg(1, " exit");
1553 log_msg(1, " unmount-me");
1554 log_msg(1,
1555 "If you're really stuck, please e-mail the mailing list.");
1556 } else {
1557 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1558 }
1559
1560 return (res);
1561}
1562
1563/**************************************************************************
1564 *END_RUN_GRUB *
1565 **************************************************************************/
1566
1567
1568/**
1569 * Install ELILO on the user's boot drive (determined by elilo.conf).
1570 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1571 * @return 0 for success, nonzero for failure.
1572 */
1573int run_elilo(bool offer_to_run_stabelilo)
1574{
1575 /** malloc **/
1576 char *command = NULL;
1577 char *tmp = NULL;
1578 char *editor = NULL;
1579
1580 int res;
1581 int done;
1582
1583 if (offer_to_run_stabelilo
1584 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1585
1586 /* interactive mode */
1587 {
1588 mvaddstr_and_log_it(g_currentY,
1589 0,
1590 "Modifying fstab and elilo.conf... ");
1591 mr_asprintf(command, "stabelilo-me");
1592 res = run_program_and_log_output(command, 3);
1593 mr_free(command);
1594
1595 if (res) {
1596 popup_and_OK
1597 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1598 for (done = FALSE; !done;) {
1599 if (!g_text_mode) {
1600 newtSuspend();
1601 }
1602 mr_asprintf(editor, "%s", find_my_editor());
1603
1604 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1605 paranoid_system(tmp);
1606 mr_free(tmp);
1607
1608 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1609 paranoid_system(tmp);
1610 mr_free(tmp);
1611 mr_free(editor);
1612
1613 if (!g_text_mode) {
1614 newtResume();
1615 }
1616// newtCls();
1617 if (ask_me_yes_or_no("Edit them again?")) {
1618 continue;
1619 }
1620 done = TRUE;
1621 }
1622 } else {
1623 log_to_screen("elilo.conf and fstab were modified OK");
1624 }
1625 } else
1626 /* nuke mode */
1627 {
1628 res = TRUE;
1629 }
1630 return (res);
1631}
1632
1633/**************************************************************************
1634 *END_RUN_ELILO *
1635 **************************************************************************/
1636
1637
1638/**
1639 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1640 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1641 * @return 0 for success, nonzero for failure.
1642 */
1643int run_lilo(bool offer_to_run_stablilo)
1644{
1645 /** malloc **/
1646 char *command = NULL;
1647 char *tmp = NULL;
1648 char *editor = NULL;
1649
1650 int res;
1651 int done;
1652 bool run_lilo_M = FALSE;
1653
1654 if (!run_program_and_log_output
1655 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1656 run_lilo_M = TRUE;
1657 }
1658
1659 if (offer_to_run_stablilo
1660 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1661
1662 /* interactive mode */
1663 {
1664 mvaddstr_and_log_it(g_currentY,
1665 0,
1666 "Modifying fstab and lilo.conf, and running LILO... ");
1667 mr_asprintf(command, "stablilo-me");
1668 res = run_program_and_log_output(command, 3);
1669 mr_free(command);
1670
1671 if (res) {
1672 popup_and_OK
1673 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1674 for (done = FALSE; !done;) {
1675 if (!g_text_mode) {
1676 newtSuspend();
1677 }
1678 mr_asprintf(editor, "%s", find_my_editor());
1679
1680 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1681 paranoid_system(tmp);
1682 mr_free(tmp);
1683
1684 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1685 paranoid_system(tmp);
1686 mr_free(tmp);
1687 mr_free(editor);
1688
1689 if (!g_text_mode) {
1690 newtResume();
1691 }
1692// newtCls();
1693 if (ask_me_yes_or_no("Edit them again?")) {
1694 continue;
1695 }
1696 res =
1697 run_program_and_log_output("chroot " MNT_RESTORING
1698 " lilo -L", 3);
1699 if (res) {
1700 res =
1701 run_program_and_log_output("chroot " MNT_RESTORING
1702 " lilo", 3);
1703 }
1704 if (res) {
1705 done =
1706 ask_me_yes_or_no
1707 ("LILO failed. Re-edit system files?");
1708 } else {
1709 done = TRUE;
1710 }
1711 }
1712 } else {
1713 log_to_screen("lilo.conf and fstab were modified OK");
1714 }
1715 } else
1716 /* nuke mode */
1717 {
1718 mvaddstr_and_log_it(g_currentY,
1719 0,
1720 "Running LILO... ");
1721 res =
1722 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1723 3);
1724 if (res) {
1725 res =
1726 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1727 3);
1728 }
1729 if (res) {
1730 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1731 log_to_screen
1732 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1733 } else {
1734 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1735 }
1736 }
1737 if (run_lilo_M) {
1738 run_program_and_log_output("chroot " MNT_RESTORING
1739 " lilo -M /dev/hda", 3);
1740 run_program_and_log_output("chroot " MNT_RESTORING
1741 " lilo -M /dev/sda", 3);
1742 }
1743 return (res);
1744}
1745
1746/**************************************************************************
1747 *END_RUN_LILO *
1748 **************************************************************************/
1749
1750
1751/**
1752 * Install a raw MBR onto @p bd.
1753 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1754 * @param bd The device to copy the stored MBR to.
1755 * @return 0 for success, nonzero for failure.
1756 */
1757int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1758{
1759 /** malloc **/
1760 char *command = NULL;
1761 char *boot_device = NULL;
1762 char *tmp = NULL;
1763 char *editor;
1764 char *p = NULL;
1765 int res;
1766 int done;
1767
1768 assert_string_is_neither_NULL_nor_zerolength(bd);
1769
1770 mr_asprintf(boot_device, "%s", bd);
1771
1772 if (offer_to_hack_scripts
1773 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1774 /* interactive mode */
1775 mvaddstr_and_log_it(g_currentY, 0,
1776 "Modifying fstab and restoring MBR... ");
1777 for (done = FALSE; !done;) {
1778 if (!run_program_and_log_output("which vi", FALSE)) {
1779 popup_and_OK("You will now edit fstab");
1780 if (!g_text_mode) {
1781 newtSuspend();
1782 }
1783 mr_asprintf(editor, "%s", find_my_editor());
1784 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1785 mr_free(editor);
1786
1787 paranoid_system(tmp);
1788 mr_free(tmp);
1789 if (!g_text_mode) {
1790 newtResume();
1791 }
1792 }
1793 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1794 if (p == NULL) {
1795 done = TRUE;
1796 mr_free(p);
1797 /* we want some warnings later on */
1798 res = 1;
1799 continue;
1800 }
1801 mr_asprintf(command, "stabraw-me %s", p);
1802 mr_free(p);
1803
1804 res = run_program_and_log_output(command, 3);
1805 mr_free(command);
1806
1807 if (res) {
1808 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1809 } else {
1810 done = TRUE;
1811 }
1812 }
1813 } else {
1814 /* nuke mode */
1815 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1816 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1817
1818 mvaddstr_and_log_it(g_currentY, 0,
1819 "Restoring MBR... ");
1820 res = run_program_and_log_output(command, 3);
1821 mr_free(command);
1822 }
1823 mr_free(boot_device);
1824
1825 if (res) {
1826 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1827 log_to_screen
1828 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1829 } else {
1830 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1831 }
1832 return (res);
1833}
1834
1835/**************************************************************************
1836 *END_RUN_RAW_MBR *
1837 **************************************************************************/
1838
1839
1840
1841/**
1842 * malloc() and set sensible defaults for the mondorestore filename variables.
1843 * @param bkpinfo The backup information structure. Fields used:
1844 * - @c bkpinfo->tmpdir
1845 * - @c bkpinfo->disaster_recovery
1846 */
1847void setup_MR_global_filenames()
1848{
1849 assert(bkpinfo != NULL);
1850
1851 malloc_string(g_filelist_imagedevs);
1852 malloc_string(g_imagedevs_restthese);
1853 malloc_string(g_mondo_home);
1854
1855 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1856 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
1857 if (! bkpinfo->disaster_recovery) {
1858 /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
1859 get_cfg_file_from_initrd();
1860 }
1861}
1862
1863/**************************************************************************
1864 *END_SET_GLOBAL_FILENAME *
1865 **************************************************************************/
1866
1867
1868/**
1869 * Copy @p input_file (containing the result of a compare) to @p output_file,
1870 * deleting spurious "changes" along the way.
1871 * @param output_file The output file to write with spurious changes removed.
1872 * @param input_file The input file, a list of changed files created by a compare.
1873 */
1874void streamline_changes_file(char *output_file, char *input_file)
1875{
1876 FILE *fin;
1877 FILE *fout;
1878 char *incoming = NULL;
1879
1880 assert_string_is_neither_NULL_nor_zerolength(output_file);
1881 assert_string_is_neither_NULL_nor_zerolength(input_file);
1882
1883 if (!(fin = fopen(input_file, "r"))) {
1884 log_OS_error(input_file);
1885 return;
1886 }
1887 if (!(fout = fopen(output_file, "w"))) {
1888 fatal_error("cannot open output_file");
1889 }
1890 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1891 if (strncmp(incoming, "etc/adjtime", 11)
1892 && strncmp(incoming, "etc/mtab", 8)
1893 && strncmp(incoming, "tmp/", 4)
1894 && strncmp(incoming, "boot/map", 8)
1895 && !strstr(incoming, "incheckentry")
1896 && strncmp(incoming, "etc/mail/statistics", 19)
1897 && strncmp(incoming, "var/", 4))
1898 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1899 mr_free(incoming);
1900 }
1901 mr_free(incoming);
1902 paranoid_fclose(fout);
1903 paranoid_fclose(fin);
1904}
1905
1906/**************************************************************************
1907 *END_STREAMLINE_CHANGES_FILE *
1908 **************************************************************************/
1909
1910
1911/**
1912 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1913 */
1914void twenty_seconds_til_yikes()
1915{
1916 int i;
1917 /* MALLOC * */
1918 char *tmp = NULL;
1919
1920 if (does_file_exist("/tmp/NOPAUSE")) {
1921 return;
1922 }
1923 open_progress_form("CAUTION",
1924 "Be advised: I am about to ERASE your hard disk(s)!",
1925 "You may press Ctrl+Alt+Del to abort safely.",
1926 "", 20);
1927 for (i = 0; i < 20; i++) {
1928 g_current_progress = i;
1929 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1930 update_progress_form(tmp);
1931 mr_free(tmp);
1932 sleep(1);
1933 }
1934 close_progress_form();
1935}
1936
1937/**************************************************************************
1938 *END_TWENTY_SECONDS_TIL_YIKES *
1939 **************************************************************************/
1940
1941
1942/**
1943 * Unmount all devices in @p p_external_copy_of_mountlist.
1944 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1945 * @return 0 for success, nonzero for failure.
1946 */
1947int unmount_all_devices(struct mountlist_itself
1948 *p_external_copy_of_mountlist)
1949{
1950 struct mountlist_itself *mountlist;
1951 int retval = 0, lino, res = 0, i;
1952 char *command = NULL;
1953 char *tmp = NULL;
1954
1955 assert(p_external_copy_of_mountlist != NULL);
1956
1957 mountlist = malloc(sizeof(struct mountlist_itself));
1958 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1959 sizeof(struct mountlist_itself));
1960 sort_mountlist_by_mountpoint(mountlist, 0);
1961
1962 run_program_and_log_output("df -m -P", 3);
1963 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1964 open_progress_form("Unmounting devices",
1965 "Unmounting all devices that were mounted,",
1966 "in preparation for the post-restoration reboot.",
1967 "", mountlist->entries);
1968 if (chdir("/")) {
1969 // FIXME
1970 }
1971 for (i = 0;
1972 i < 10
1973 &&
1974 run_program_and_log_output
1975 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1976 i++) {
1977 sleep(1);
1978 log_msg(2, "Waiting for buffer() to finish");
1979 }
1980
1981 sync();
1982
1983 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1984 if (run_program_and_log_output(tmp, FALSE)) {
1985 log_msg(1,
1986 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1987 }
1988 paranoid_free(tmp);
1989 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1990 run_program_and_log_output("mkdir -p " MNT_RESTORING
1991 "/mnt/.boot.d", 5);
1992 }
1993
1994 /* Unmounting the local /proc and /sys first */
1995 run_program_and_log_output("umount -d " MNT_RESTORING "/proc",3);
1996 run_program_and_log_output("umount -d " MNT_RESTORING "/sys",3);
1997
1998 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
1999 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2000 continue;
2001 }
2002 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
2003 update_progress_form(tmp);
2004
2005 if (is_this_device_mounted(mountlist->el[lino].device)) {
2006 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2007 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
2008 } else {
2009 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2010 mr_asprintf(command, "umount -d %s/", MNT_RESTORING);
2011 log_msg(3,
2012 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2013 } else {
2014 mr_asprintf(command, "umount -d " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
2015
2016 /* To support latest Ubuntu where /var is a separate FS
2017 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
2018 * we need to create some dirs under the real / before unmounting it */
2019 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
2020 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
2021 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
2022 }
2023 }
2024 }
2025 log_msg(10, "The 'umount' command is '%s'", command);
2026 res = run_program_and_log_output(command, 3);
2027 mr_free(command);
2028 } else {
2029 mr_strcat(tmp, "...not mounted anyway :-) OK");
2030 res = 0;
2031 }
2032 g_current_progress++;
2033 if (res) {
2034 mr_strcat(tmp, "...Failed");
2035 retval++;
2036 log_to_screen(tmp);
2037 } else {
2038 log_msg(2, tmp);
2039 }
2040 paranoid_free(tmp);
2041 }
2042 close_progress_form();
2043 if (retval) {
2044 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2045 } else {
2046 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2047 }
2048 if (retval) {
2049 log_to_screen("Unable to unmount some of your partitions.");
2050 } else {
2051 log_to_screen("All partitions were unmounted OK.");
2052 }
2053 free(mountlist);
2054 return (retval);
2055}
2056
2057/**************************************************************************
2058 *END_UNMOUNT_ALL_DEVICES *
2059 **************************************************************************/
2060
2061/**************************************************************************
2062 *END_GET_CFG_FILE_FROM_ARCHIVE *
2063 **************************************************************************/
2064
2065/* @} - end restoreUtilityGroup */
2066
2067void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage)
2068{
2069 struct raidlist_itself *raidlist;
2070 int unfinished_mdstat_devices = 9999;
2071 int i = 0;
2072 char *screen_message = NULL;
2073
2074 raidlist = malloc(sizeof(struct raidlist_itself));
2075
2076 assert(wait_for_percentage <= 100);
2077 log_it("wait_until_software_raids_are_prepped");
2078 while (unfinished_mdstat_devices > 0) {
2079 // FIXME: Prefix '/dev/' should really be dynamic!
2080 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2081 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2082 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2083 return;
2084 }
2085 for (unfinished_mdstat_devices = 0; i <= raidlist->entries; i++) {
2086 if (raidlist->el[i].progress < wait_for_percentage) {
2087 unfinished_mdstat_devices++;
2088 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2089 {
2090 continue;
2091 }
2092 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2093 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2094 open_evalcall_form(screen_message);
2095 mr_free(screen_message);
2096
2097 while (raidlist->el[i].progress < wait_for_percentage) {
2098 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2099 update_evalcall_form(raidlist->el[i].progress);
2100 sleep(2);
2101 // FIXME: Prefix '/dev/' should really be dynamic!
2102 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2103 break;
2104 }
2105 }
2106 close_evalcall_form();
2107 }
2108 }
2109 }
2110 paranoid_free(raidlist);
2111}
Note: See TracBrowser for help on using the repository browser.