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

Last change on this file since 3161 was 3161, checked in by Bruno Cornec, 11 years ago
  • Apply fixes to 3.1 tree so that at least mondo compiles again (but that branch probably doesn't work at all again).
  • Property svn:keywords set to Id
File size: 64.7 KB
Line 
1/***************************************************************************
2$Id: mondo-rstr-tools.c 3161 2013-06-25 20:53:14Z 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); 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 mr_asprintf(tmp, "%s", file);
143 mr_free(file);
144
145 mr_asprintf(file, "%s", tmp + 1);
146 mr_free(tmp);
147}
148log_msg(2, "Checking to see if f=%s, file=%s, is in the list of biggiefiles", f, file);
149mr_asprintf(command, "grep -E '^%s$' %s", file, list_fname);
150mr_free(file);
151
152res = run_program_and_log_output(command, FALSE);
153mr_free(command);
154if (res) {
155 return (FALSE);
156} else {
157 return (TRUE);
158}
159}
160
161/**************************************************************************
162*END_IS_FILE_IN_LIST *
163**************************************************************************/
164
165
166
167/**
168* Set up an ISO backup.
169* @param bkpinfo The backup information structure. Fields used:
170* - @c bkpinfo->backup_media_type
171* - @c bkpinfo->disaster_recovery
172* - @c bkpinfo->isodir
173* @param nuke_me_please If TRUE, we're in nuke mode; if FALSE we're in interactive mode.
174* @return 0 for success, nonzero for failure.
175*/
176int iso_fiddly_bits(bool nuke_me_please)
177{
178 char *mount_isodir_command = NULL;
179 char *command = NULL;
180 char *mds = NULL;
181 int retval = 0, i;
182 char *isodir_format = NULL;
183
184g_ISO_restore_mode = TRUE;
185mr_free(g_isodir_device);
186g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
187if (bkpinfo->disaster_recovery) {
188 /* Patch Conor Daly 26-june-2004
189 * Don't let this clobber an existing bkpinfo->isodir */
190 if (!bkpinfo->isodir[0]) {
191 mr_free(bkpinfo->isodir);
192 mr_asprintf(bkpinfo->isodir, "/tmp/isodir");
193 }
194 /* End patch */
195 mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
196 run_program_and_log_output(command, 5);
197 mr_free(command);
198 log_msg(2, "Setting isodir to %s", bkpinfo->isodir);
199}
200
201/* g_isodir_device is passed and modified in this function - memory is managed correctly in it */
202if (!get_isodir_info(g_isodir_device, isodir_format, bkpinfo->isodir, bkpinfo->subdir, nuke_me_please)) {
203 mr_free(isodir_format);
204 return (1);
205}
206paranoid_system("umount -d " MNT_CDROM " 2> /dev/null"); /* just in case */
207
208if (is_this_device_mounted(g_isodir_device)) {
209 log_to_screen("WARNING - isodir is already mounted");
210} else {
211 mr_asprintf(mount_isodir_command, "mount %s", g_isodir_device);
212 if (isodir_format) {
213 mr_strcat(mount_isodir_command, " -t %s", isodir_format);
214 }
215
216 mr_strcat(mount_isodir_command, " -o ro %s", bkpinfo->isodir);
217 run_program_and_log_output("df -m -P", FALSE);
218 log_msg(1, "The 'mount' command is '%s'. PLEASE report this command to be if you have problems, ok?", mount_isodir_command);
219 if (run_program_and_log_output(mount_isodir_command, FALSE)) {
220 popup_and_OK
221 ("Cannot mount the device where the ISO files are stored.");
222 return (1);
223 }
224 paranoid_free(mount_isodir_command);
225 log_to_screen
226 ("I have mounted the device where the ISO files are stored.");
227}
228mr_free(isodir_format);
229
230if (!IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
231 mount_media();
232}
233i = what_number_cd_is_this(); /* has the side-effect of calling mount_media() */
234mds = media_descriptor_string(bkpinfo->backup_media_type);
235mr_free(mds);
236
237log_msg(1, "%s #%d has been mounted via loopback mount", mds, i);
238if (i < 0) {
239 popup_and_OK("Cannot find ISO images in the directory you specified.");
240 retval = 1;
241}
242log_msg(2, "bkpinfo->isodir is now %s", bkpinfo->isodir);
243return (retval);
244}
245
246
247
248
249/**
250* Kill all Petris processes.
251*/
252void kill_petris(void) {
253 kill_anything_like_this("petris");
254}
255
256/**************************************************************************
257*END_KILL_PETRIS *
258**************************************************************************/
259
260
261/**
262 * Mount @p device at @p mpt as @p format.
263 * @param device The device (/dev entry) to mount.
264 * @param mpt The directory to mount it on.
265 * @param format The filesystem type of @p device.
266 * @param writeable If TRUE, mount read-write; if FALSE, mount read-only.
267 * @return 0 for success, nonzero for failure.
268 */
269int mount_device(char *device, char *mpt, char *format, bool writeable)
270{
271int res = 0;
272
273/** malloc **/
274char *tmp = NULL;
275char *command = NULL;
276char *mountdir = NULL;
277char *mountpoint = NULL;
278char *additional_parameters = NULL;
279
280assert_string_is_neither_NULL_nor_zerolength(device);
281assert_string_is_neither_NULL_nor_zerolength(mpt);
282assert(format != NULL);
283
284 if (!strcmp(mpt, "/1")) {
285 mr_asprintf(mountpoint, "/");
286 log_msg(3, "Mommm! SME is being a dildo!");
287 } else {
288 mr_asprintf(mountpoint, "%s", mpt);
289 }
290
291 if (!strcmp(mountpoint, "lvm")) {
292 return (0);
293 }
294 if (!strcmp(mountpoint, "image")) {
295 return (0);
296 }
297 mr_asprintf(tmp, "Mounting device %s ", device);
298 log_msg(1, tmp);
299 /* Deal with additional params only if not /proc or /sys */
300 mr_asprintf(additional_parameters, "");
301 if (strcmp(format, "proc") && strcmp(format, "sys")) {
302 if (writeable) {
303 mr_strcat(additional_parameters, "-o rw");
304 } else {
305 mr_strcat(additional_parameters, "-o ro");
306 }
307 tmp = find_home_of_exe("setfattr");
308 if (tmp) {
309 mr_strcat(additional_parameters, ",user_xattr");
310 }
311 mr_free(tmp);
312
313 tmp = find_home_of_exe("setfacl");
314 if (tmp) {
315 mr_strcat(additional_parameters, ",acl");
316 }
317 mr_free(tmp);
318 }
319
320 if (!strcmp(mountpoint, "swap")) {
321 mr_asprintf(command, "swapon %s", device);
322 mr_asprintf(mountdir, "swap");
323 } else {
324 if (!strcmp(mountpoint, "/")) {
325 mr_asprintf(mountdir, "%s", MNT_RESTORING);
326 } else {
327 mr_asprintf(mountdir, "%s%s", MNT_RESTORING, mountpoint);
328 }
329 mr_asprintf(command, "mkdir -p %s", mountdir);
330 run_program_and_log_output(command, FALSE);
331 mr_free(command);
332
333 mr_asprintf(command, "mount -t %s %s %s %s 2>> %s", format, device, additional_parameters, mountdir, MONDO_LOGFILE);
334 log_msg(2, "command='%s'", command);
335 }
336 mr_free(additional_parameters);
337
338 res = run_program_and_log_output(command, TRUE);
339 if (res && (strstr(command, "xattr") || strstr(command, "acl"))) {
340 log_msg(1, "Re-trying without the fancy extra parameters");
341 mr_free(command);
342 mr_asprintf(command, "mount -t %s %s %s 2>> %s", format, device, mountdir, MONDO_LOGFILE);
343 res = run_program_and_log_output(command, TRUE);
344 }
345 if (res) {
346 log_msg(1, "Unable to mount device %s (type %s) at %s", device, format, mountdir);
347 log_msg(1, "command was '%s'", command);
348 if (!strcmp(mountpoint, "swap")) {
349 log_to_screen(tmp);
350 } else {
351 log_msg(2, "Retrying w/o the '-t' switch");
352 mr_free(command);
353 mr_asprintf(command, "mount %s %s 2>> %s", device, mountdir, MONDO_LOGFILE);
354 log_msg(2, "2nd command = '%s'", command);
355 res = run_program_and_log_output(command, TRUE);
356 if (res == 0) {
357 log_msg(1,
358 "That's OK. I called mount w/o a filesystem type and it worked fine in the end.");
359 } else {
360 log_to_screen(tmp);
361 }
362 }
363 }
364
365 if (res && !strcmp(mountpoint, "swap")) {
366 log_msg(2, "That's ok. It's just a swap partition.");
367 log_msg(2, "Non-fatal error. Returning 0.");
368 res = 0;
369 }
370
371mr_free(tmp);
372mr_free(command);
373mr_free(mountdir);
374mr_free(mountpoint);
375
376 return (res);
377}
378/**************************************************************************
379 *END_MOUNT_DEVICE *
380**************************************************************************/
381
382
383/**
384 * Mount all devices in @p p_external_copy_of_mountlist on @p MNT_RESTORING.
385 * @param p_external_copy_of_mountlist The mountlist containing devices to be mounted.
386 * @param writeable If TRUE, then mount read-write; if FALSE mount read-only.
387 * @return The number of errors encountered (0 for success).
388 */
389int mount_all_devices(struct mountlist_itself *p_external_copy_of_mountlist, bool writeable)
390{
391int retval = 0, lino, res;
392char *tmp = NULL;
393char *these_failed = NULL;
394struct mountlist_itself *mountlist = NULL;
395
396assert(p_external_copy_of_mountlist != NULL);
397mountlist = malloc(sizeof(struct mountlist_itself));
398memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
399 sizeof(struct mountlist_itself));
400 sort_mountlist_by_mountpoint(mountlist, 0);
401
402
403 mvaddstr_and_log_it(g_currentY, 0, "Mounting devices ");
404 open_progress_form("Mounting devices", "I am now mounting all the drives.", "This should not take long.", "", mountlist->entries);
405
406 mr_asprintf(these_failed, "");
407 for (lino = 0; lino < mountlist->entries; lino++) {
408 if (!strcmp(mountlist->el[lino].device, "/proc")) {
409 log_msg(1, "Again with the /proc - why is this in your mountlist?");
410 } else if (is_this_device_mounted(mountlist->el[lino].device)) {
411 log_to_screen("%s is already mounted", mountlist->el[lino].device);
412 } else if (strcmp(mountlist->el[lino].mountpoint, "none")
413 && strcmp(mountlist->el[lino].mountpoint, "lvm")
414 && strcmp(mountlist->el[lino].mountpoint, "raid")
415 && strcmp(mountlist->el[lino].mountpoint, "image")) {
416 mr_asprintf(tmp, "Mounting %s", mountlist->el[lino].device);
417 update_progress_form(tmp);
418 mr_free(tmp);
419 res = mount_device(mountlist->el[lino].device, mountlist->el[lino].mountpoint, mountlist->el[lino].format, writeable);
420
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);
662
663media_specified_by_user = bkpinfo->backup_media_type; // or 'none', if not specified
664
665if ((value = read_cfg_var(cfg_file, "backup-media-type")) != NULL) {
666 if (!strcmp(value, "cdstream")) {
667 bkpinfo->backup_media_type = cdstream;
668 } else if (!strcmp(value, "cdr")) {
669 bkpinfo->backup_media_type = cdr;
670 } else if (!strcmp(value, "cdrw")) {
671 bkpinfo->backup_media_type = cdrw;
672 } else if (!strcmp(value, "dvd")) {
673 bkpinfo->backup_media_type = dvd;
674 } else if (!strcmp(value, "usb")) {
675 bkpinfo->backup_media_type = usb;
676 bkpinfo->please_dont_eject = TRUE;
677 } else if (!strcmp(value, "iso")) {
678 // Patch by Conor Daly - 2004/07/12
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
690 ("Re-jigging configuration AGAIN. CD-R, not ISO.");
691 }
692 }
693 mr_free(bkpinfo->prefix);
694 mr_free(value);
695 if ((value = read_cfg_var(cfg_file, "iso-prefix")) == 0) {
696 mr_asprintf(bkpinfo->prefix, "%s", value);
697 } else {
698 mr_asprintf(bkpinfo->prefix, "%s", STD_PREFIX);
699 }
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[0] = 1999 * 1024;
757 bkpinfo->media_size[1] = 650; /* good guess */
758 } else if (bkpinfo->backup_media_type == usb) {
759 envtmp1 = getenv("MRUSBDEV");
760 if (envtmp1 == NULL) {
761 if ((value = read_cfg_var(cfg_file, "usb-dev")) == NULL) {
762 fatal_error("Cannot get USB device name from cfg file");
763 }
764 } else {
765 mr_asprintf(value,"%s", envtmp1);
766 }
767 mr_free(bkpinfo->media_device);
768 mr_asprintf(bkpinfo->media_device, "%s1", value);
769 mr_free(value);
770 log_msg(2, "Backup medium is USB --- dev=%s", bkpinfo->media_device);
771 } else if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
772 if ((value = read_cfg_var(cfg_file, "media-dev")) == NULL) {
773 fatal_error("Cannot get tape device name from cfg file");
774 }
775 mr_free(bkpinfo->media_device);
776 bkpinfo->media_device = value;
777
778 value = read_cfg_var(cfg_file, "media-size");
779 if (value != NULL) {
780 bkpinfo->media_size[1] = atol(value);
781 mr_free(value);
782 } else {
783 bkpinfo->media_size[1] = 0L;
784 }
785 log_msg(2, "Backup medium is TAPE --- dev=%s", bkpinfo->media_device);
786 } else {
787 mr_free(bkpinfo->media_device);
788 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* we don't really need this var */
789 bkpinfo->media_size[0] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
790 bkpinfo->media_size[1] = 1999 * 1024; /* 650, probably, but we don't need this var anyway */
791 log_msg(2, "Backup medium is CD-R[W]");
792 }
793} else {
794 log_msg(2, "Not in Disaster Recovery Mode. No need to derive device name from config file.");
795}
796
797value = read_cfg_var(cfg_file, "use-star");
798if (value && strstr(value, "yes")) {
799 bkpinfo->use_star = TRUE;
800 log_msg(1, "Goody! ... bkpinfo->use_star is now true.");
801}
802mr_free(value);
803
804value = read_cfg_var(cfg_file, "obdr");
805if (value && strstr(value, "TRUE")) {
806 bkpinfo->use_obdr = TRUE;
807 log_msg(1, "OBDR mode activated");
808}
809mr_free(value);
810
811value = read_cfg_var(cfg_file, "acl");
812if (value && strstr(value, "TRUE")) {
813 mr_asprintf(g_getfacl,"setfacl");
814 log_msg(1, "We will restore ACLs");
815 tmp = find_home_of_exe("setfacl");
816 if (!tmp) {
817 log_msg(1, "Unable to restore ACLs as no setfacl found");
818 }
819 mr_free(tmp);
820}
821mr_free(value);
822
823value = read_cfg_var(cfg_file, "xattr");
824if (value && strstr(value, "TRUE")) {
825 mr_asprintf(g_getfattr,"setfattr");
826 log_msg(1, "We will restore XATTRs");
827 tmp = find_home_of_exe("setfattr");
828 if (!tmp) {
829 log_msg(1, "Unable to restore XATTRs as no setfattr found");
830 }
831 mr_free(tmp);
832}
833mr_free(value);
834
835value = read_cfg_var(cfg_file, "internal-tape-block-size");
836if (value != NULL) {
837 bkpinfo->internal_tape_block_size = atol(value);
838} else {
839 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
840}
841log_msg(1, "Internal tape block size set to %ld", bkpinfo->internal_tape_block_size);
842mr_free(value);
843
844value = read_cfg_var(cfg_file, "use-lzma");
845if (value && strstr(value, "yes")) {
846 bkpinfo->use_lzma = TRUE;
847 bkpinfo->use_lzo = FALSE;
848 bkpinfo->use_gzip = FALSE;
849 mr_free(bkpinfo->zip_exe);
850 mr_asprintf(bkpinfo->zip_exe, "lzma");
851 mr_free(bkpinfo->zip_suffix);
852 mr_asprintf(bkpinfo->zip_suffix, "lzma");
853}
854mr_free(value);
855
856value = read_cfg_var(cfg_file, "use-lzo");
857if (value && strstr(value, "yes")) {
858 bkpinfo->use_lzma = FALSE;
859 bkpinfo->use_lzo = TRUE;
860 bkpinfo->use_gzip = FALSE;
861 mr_free(bkpinfo->zip_exe);
862 mr_asprintf(bkpinfo->zip_exe, "lzop");
863 mr_free(bkpinfo->zip_suffix);
864 mr_asprintf(bkpinfo->zip_suffix, "lzo");
865}
866mr_free(value);
867
868value = read_cfg_var(cfg_file, "use-gzip");
869if (value && strstr(value, "yes")) {
870 bkpinfo->use_lzma = FALSE;
871 bkpinfo->use_lzo = FALSE;
872 bkpinfo->use_gzip = TRUE;
873 mr_free(bkpinfo->zip_exe);
874 mr_asprintf(bkpinfo->zip_exe, "gzip");
875 mr_free(bkpinfo->zip_suffix);
876 mr_asprintf(bkpinfo->zip_suffix, "gz");
877}
878mr_free(value);
879
880value = read_cfg_var(cfg_file, "use-comp");
881if (value && strstr(value, "yes")) {
882 bkpinfo->use_lzma = FALSE;
883 bkpinfo->use_lzo = FALSE;
884 bkpinfo->use_gzip = FALSE;
885 mr_free(bkpinfo->zip_exe);
886 mr_asprintf(bkpinfo->zip_exe, "bzip2");
887 mr_free(bkpinfo->zip_suffix);
888 mr_asprintf(bkpinfo->zip_suffix, "bz2");
889}
890mr_free(value);
891
892if (bkpinfo->zip_exe == NULL) {
893 mr_asprintf(bkpinfo->zip_exe, "none");
894}
895if (bkpinfo->zip_suffix == NULL) {
896 mr_asprintf(bkpinfo->zip_suffix, "");
897}
898
899value = read_cfg_var(cfg_file, "differential");
900if (value && (!strcmp(value, "yes") || !strcmp(value, "1"))) {
901 bkpinfo->differential = TRUE;
902}
903log_msg(2, "differential var = '%s'", value);
904mr_free(value);
905if (bkpinfo->differential) {
906 log_msg(2, "THIS IS A DIFFERENTIAL BACKUP");
907} else {
908 log_msg(2, "This is a regular (full) backup");
909}
910
911tmp = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "please-dont-eject");
912tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
913if (tmp || strstr(tmp1, "donteject")) {
914 bkpinfo->please_dont_eject = TRUE;
915 log_msg(2, "Ok, I shan't eject when restoring! Groovy.");
916}
917mr_free(tmp);
918mr_free(tmp1);
919
920if (bkpinfo->backup_media_type == netfs) {
921 if (!cfgf) {
922 if (bkpinfo->netfs_mount) {
923 log_msg(2, "netfs_mount remains %s", bkpinfo->netfs_mount);
924 }
925 if (bkpinfo->netfs_remote_dir) {
926 log_msg(2, "netfs_remote_dir remains %s", bkpinfo->netfs_remote_dir);
927 }
928 log_msg(2, "...cos it wouldn't make sense to abandon the values that GOT ME to this config file in the first place");
929 } else {
930 mr_free(bkpinfo->netfs_mount);
931 bkpinfo->netfs_mount = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-mount");
932
933 mr_free(bkpinfo->netfs_remote_dir);
934 bkpinfo->netfs_remote_dir = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "netfs-server-path");
935
936 if (bkpinfo->netfs_mount != NULL) {
937 log_msg(2, "netfs_mount is %s", bkpinfo->netfs_mount);
938 }
939 if (bkpinfo->netfs_remote_dir != NULL) {
940 log_msg(2, "netfs_remote_dir is %s", bkpinfo->netfs_remote_dir);
941 }
942 if (bkpinfo->netfs_proto != NULL) {
943 log_msg(2, "netfs_proto is %s", bkpinfo->netfs_proto);
944 }
945 if (bkpinfo->netfs_user != NULL) {
946 log_msg(2, "netfs_user is %s", bkpinfo->netfs_user);
947 }
948 }
949 tmp1 = call_program_and_get_last_line_of_output("cat " CMDLINE,TRUE);
950 if (strstr(tmp1, "pxe")) {
951 mr_free(tmp1);
952 /* We need to override values in PXE mode as it's
953 * already done in start-netfs */
954 envtmp1 = getenv("netfsmount");
955 if (envtmp1 == NULL) {
956 fatal_error("no netfsmount variable in environment");
957 }
958 envtmp2 = getenv("dirimg");
959 if (envtmp2 == NULL) {
960 fatal_error("no dirimg variable in environment");
961 }
962 mr_free(bkpinfo->netfs_mount);
963 mr_asprintf(bkpinfo->netfs_mount, "%s", envtmp1);
964
965 mr_free(bkpinfo->netfs_remote_dir);
966 mr_asprintf(bkpinfo->netfs_remote_dir, "%s", envtmp2);
967 } else {
968 mr_free(tmp1);
969 }
970
971} else if (bkpinfo->backup_media_type == iso) {
972 /* Patch by Conor Daly 23-june-2004
973 * to correctly mount iso-dev and set a sensible
974 * isodir in disaster recovery mode
975 */
976 mr_asprintf(old_isodir, "%s", bkpinfo->isodir);
977 iso_mnt = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-mnt");
978 iso_path = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "isodir");
979 mr_free(bkpinfo->isodir);
980 mr_asprintf(bkpinfo->isodir, "%s%s", iso_mnt, iso_path);
981 mr_free(iso_mnt);
982
983 if (!bkpinfo->isodir[0]) {
984 mr_free(bkpinfo->isodir);
985 bkpinfo->isodir = old_isodir;
986 } else {
987 mr_free(old_isodir);
988 }
989 if (!bkpinfo->disaster_recovery) {
990 if (strcmp(old_isodir, bkpinfo->isodir)) {
991 log_it("user nominated isodir %s differs from archive, keeping user's choice: %s\n", bkpinfo->isodir, old_isodir );
992 mr_free(bkpinfo->isodir);
993 bkpinfo->isodir = old_isodir;
994 } else {
995 mr_free(old_isodir);
996 }
997 }
998 mr_free(g_isodir_device);
999 g_isodir_device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "iso-dev");
1000 log_msg(2, "isodir=%s; iso-dev=%s", bkpinfo->isodir, g_isodir_device);
1001
1002 if (bkpinfo->disaster_recovery) {
1003 if (is_this_device_mounted(g_isodir_device)) {
1004 log_msg(2, "NB: isodir is already mounted");
1005 /* Find out where it's mounted */
1006 mr_asprintf(command, "mount | grep -E '^%s' | tail -n1 | cut -d' ' -f3", g_isodir_device);
1007 log_it("command = %s", command);
1008 iso_mnt = call_program_and_get_last_line_of_output(command,TRUE);
1009 log_it("res of it = %s", iso_mnt);
1010 mr_free(command);
1011 } else {
1012 mr_asprintf(iso_mnt, "/tmp/isodir");
1013 mr_asprintf(tmp1, "mkdir -p %s", iso_mnt);
1014 run_program_and_log_output(tmp1, 5);
1015 mr_free(tmp1);
1016
1017 mr_asprintf(tmp1, "mount %s %s", g_isodir_device, iso_mnt);
1018 if (run_program_and_log_output(tmp1, 3)) {
1019 log_msg(1, "Unable to mount isodir. Perhaps this is really a CD backup?");
1020 bkpinfo->backup_media_type = cdr;
1021 mr_free(bkpinfo->media_device);
1022 mr_asprintf(bkpinfo->media_device, "/dev/cdrom"); /* superfluous */
1023 if (mount_media()) {
1024 mr_free(tmp1);
1025 fatal_error("Unable to mount isodir. Failed to mount CD-ROM as well.");
1026 } else {
1027 log_msg(1, "You backed up to disk, then burned some CDs.");
1028 }
1029 }
1030 mr_free(tmp1);
1031 }
1032 /* bkpinfo->isodir should now be the true path to prefix-1.iso etc... */
1033 if (bkpinfo->backup_media_type == iso) {
1034 mr_free(bkpinfo->isodir);
1035 mr_asprintf(tmp1, "%s%s", iso_mnt, iso_path);
1036 bkpinfo->isodir = tmp1;
1037 }
1038 mr_free(iso_mnt);
1039 }
1040 mr_free(iso_path);
1041}
1042
1043if (media_specified_by_user != none) {
1044 if (! bkpinfo->disaster_recovery) {
1045 if (bkpinfo->backup_media_type != media_specified_by_user) {
1046 log_msg(2,
1047 "bkpinfo->backup_media_type != media_specified_by_user, so I'd better ask :)");
1048 interactively_obtain_media_parameters_from_user(FALSE);
1049 media_specified_by_user = bkpinfo->backup_media_type;
1050 get_cfg_file_from_initrd();
1051 }
1052 }
1053 bkpinfo->backup_media_type = media_specified_by_user;
1054}
1055g_backup_media_type = bkpinfo->backup_media_type;
1056paranoid_free(value);
1057return (0);
1058
1059}
1060
1061/**************************************************************************
1062*END_READ_CFG_FILE_INTO_BKPINFO *
1063**************************************************************************/
1064
1065
1066
1067
1068/**
1069 * Allow the user to edit the filelist and biggielist.
1070 * The filelist is unlinked after it is read.
1071 * @param bkpinfo The backup information structure. Fields used:
1072 * - @c bkpinfo->backup_media_type
1073 * - @c bkpinfo->isodir
1074 * - @c bkpinfo->media_device
1075 * - @c bkpinfo->tmpdir
1076 * @return The filelist structure containing the information read from disk.
1077 */
1078struct
1079s_node *process_filelist_and_biggielist()
1080{
1081struct s_node *filelist;
1082
1083char *command = NULL;
1084char *tmp;
1085char *q;
1086int res = 0;
1087pid_t pid;
1088
1089assert(bkpinfo != NULL);
1090malloc_string(tmp);
1091
1092 if (getcwd(tmp, MAX_STR_LEN) == NULL) {
1093 // FIXME
1094 }
1095 if (chdir(bkpinfo->tmpdir)) {
1096 // FIXME
1097 }
1098 log_msg(1, "chdir(%s)", bkpinfo->tmpdir);
1099 log_to_screen("Extracting filelist and biggielist from media...");
1100 if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
1101 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);
1102 log_msg(1, "tarcommand = %s", command);
1103 run_program_and_log_output(command, 1);
1104 mr_free(command);
1105
1106 } else {
1107 log_msg(2, "Calling insist_on_this_cd_number; bkpinfo->isodir=%s", bkpinfo->isodir);
1108 insist_on_this_cd_number(1);
1109 log_msg(2, "Back from iotcn");
1110 run_program_and_log_output("mount", 1);
1111 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");
1112
1113 log_msg(1, "tarcommand = %s", command);
1114 run_program_and_log_output(command, 1);
1115 mr_free(command);
1116
1117 if (!does_file_exist(MINDI_CACHE"/biggielist.txt")) {
1118 fatal_error("all.tar.gz did not include "MINDI_CACHE"/biggielist.txt");
1119 }
1120 if (!does_file_exist(MINDI_CACHE"/filelist.full.gz")) {
1121 fatal_error("all.tar.gz did not include "MINDI_CACHE"/filelist.full.gz");
1122 }
1123 }
1124 if (chdir(tmp)) {
1125 // FIXME
1126 }
1127
1128 log_msg(2, "Forking");
1129 pid = fork();
1130 switch (pid) {
1131 case -1:
1132 fatal_error("Forking error");
1133 break;
1134
1135 case 0:
1136 log_to_screen("Pre-processing filelist");
1137 mr_asprintf(command, "grep -E '^/dev/.*' "MINDI_CACHE"/biggielist.txt > %s 2> /dev/null", g_filelist_imagedevs);
1138 paranoid_system(command);
1139 mr_free(command);
1140 exit(0);
1141 break;
1142
1143 default:
1144 open_evalcall_form("Pre-processing filelist");
1145 while (!waitpid(pid, (int *) 0, WNOHANG)) {
1146 usleep(100000);
1147 update_evalcall_form(0);
1148 }
1149 }
1150 close_evalcall_form();
1151
1152 log_msg(3, "loading filelist");
1153 filelist = load_filelist(MINDI_CACHE"/filelist.full.gz");
1154 log_msg(3, "deleting original filelist");
1155 unlink(MINDI_CACHE"/filelist.full.gz");
1156 if (g_text_mode) {
1157 q = NULL;
1158 while (q == NULL) {
1159 printf("Restore which directory? --> ");
1160 mr_getline(q, stdin);
1161 }
1162 toggle_path_selection(filelist, q, TRUE);
1163 if (strlen(q) == 0) {
1164 res = 1;
1165 } else {
1166 res = 0;
1167 }
1168 mr_free(q);
1169 } else {
1170 res = edit_filelist(filelist);
1171 }
1172 if (res) {
1173 log_msg(2, "User hit 'cancel'. Freeing filelist and aborting.");
1174 free_filelist(filelist);
1175 return (NULL);
1176 }
1177 ask_about_these_imagedevs(g_filelist_imagedevs, g_imagedevs_restthese);
1178 close_evalcall_form();
1179
1180 // NB: It's not necessary to add biggielist.txt to the filelist.full
1181 // file. The filelist.full file already contains the filename of EVERY
1182 // file backed up - regular and biggie files.
1183
1184 // However, we do want to make sure the imagedevs selected by the user
1185 // are flagged for restoring.
1186 if (length_of_file(g_imagedevs_restthese) > 2) {
1187 add_list_of_files_to_filelist(filelist, g_imagedevs_restthese,
1188 TRUE);
1189 }
1190
1191 paranoid_free(tmp);
1192 return (filelist);
1193}
1194
1195/**************************************************************************
1196 *END_ PROCESS_FILELIST_AND_BIGGIELIST *
1197 **************************************************************************/
1198
1199
1200
1201
1202/**
1203 * Make a backup copy of <tt>path_root</tt>/<tt>filename</tt>.
1204 * The backup filename is the filename of the original with ".pristine" added.
1205 * @param path_root The place where the filesystem is mounted (e.g. MNT_RESTORING).
1206 * @param filename The filename (absolute path) within @p path_root.
1207 * @return 0 for success, nonzero for failure.
1208 */
1209int backup_crucial_file(char *path_root, char *filename)
1210{
1211 char *tmp = NULL;
1212 char *command = NULL;
1213 int res;
1214
1215 assert(path_root != NULL);
1216 assert_string_is_neither_NULL_nor_zerolength(filename);
1217
1218 mr_asprintf(tmp, "%s/%s", path_root, filename);
1219 mr_asprintf(command, "cp -f %s %s.pristine", tmp, tmp);
1220 mr_free(tmp);
1221
1222 res = run_program_and_log_output(command, 5);
1223 mr_free(command);
1224 return (res);
1225}
1226
1227void offer_to_make_initrd() {
1228
1229if (bkpinfo->restore_mode != nuke) {
1230 if (ask_me_yes_or_no
1231 ("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 ?")) {
1232 log_msg(1,"Launching shell for manual initrd recreation");
1233 if (does_file_exist(MNT_RESTORING"/etc/arch-release")) {
1234 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");
1235 } else {
1236 popup_and_OK("You'll now be chrooted under your future / partition.\nGo under /boot and rebuild your initrd with\nmkinitrd -f -v initrd-2.x.y.img 2.x.y e.g.\nThen type exit to finish.");
1237 }
1238 mvaddstr_and_log_it(g_currentY, 0, "Modifying initrd...");
1239 if (!g_text_mode) {
1240 newtSuspend();
1241 }
1242 paranoid_system("chroot " MNT_RESTORING);
1243 if (!g_text_mode) {
1244 newtResume();
1245 }
1246 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1247 } else {
1248 return;
1249 }
1250} else {
1251 log_to_screen("Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1252 log_msg(1,"Non-interactive mode: no way to give you the keyboard so that you re-generate your initrd. Hope it's OK");
1253}
1254}
1255
1256
1257/**
1258 * Install the user's boot loader in the MBR.
1259 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
1260 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1261 * @return 0 for success, nonzero for failure.
1262 */
1263int run_boot_loader(bool offer_to_hack_scripts)
1264{
1265 int res;
1266 int retval = 0;
1267
1268 /** malloc *******/
1269 char *device = NULL;
1270 char *name = NULL;
1271 char *cmd = NULL;
1272
1273 /* In order to have a working bootloader, we need to have all devices
1274 * ready in the chroot. If they are not there (udev) then copy them from
1275 * the current /dev location
1276 */
1277 mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
1278 run_program_and_log_output(cmd, 3);
1279 paranoid_free(cmd);
1280
1281 backup_crucial_file(MNT_RESTORING, "/etc/fstab");
1282 backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
1283 backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
1284 backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
1285 backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
1286 backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
1287 backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
1288 backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
1289 backup_crucial_file(MNT_RESTORING, "/etc/mtab");
1290 device = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.device");
1291 name = read_cfg_var(MINDI_CACHE"/mondorestore.cfg", "bootloader.name");
1292 log_msg(2, "run_boot_loader: device='%s', name='%s'", device, name);
1293 sync();
1294
1295 offer_to_make_initrd();
1296 if (!strcmp(name, "LILO")) {
1297 res = run_lilo(offer_to_hack_scripts);
1298 } else if (!strcmp(name, "ELILO")) {
1299 res = run_elilo(offer_to_hack_scripts);
1300 } else if (!strcmp(name, "GRUB")) {
1301 res = run_grub(offer_to_hack_scripts, device);
1302 } else if (!strcmp(name, "RAW")) {
1303 res = run_raw_mbr(offer_to_hack_scripts, device);
1304 }
1305#ifdef __FreeBSD__
1306 else if (!strcmp(name, "BOOT0")) {
1307 mr_asprintf(tmp, "boot0cfg -B %s", device);
1308 res = run_program_and_log_output(tmp, FALSE);
1309 paranoid_free(tmp);
1310 } else {
1311 mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
1312 if (!system(tmp)) {
1313 mr_free(tmp);
1314 mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
1315 res = run_program_and_log_output(tmp, 3);
1316 } else {
1317 log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
1318 }
1319 mr_free(tmp);
1320 }
1321#else
1322 else {
1323 log_to_screen
1324 ("Unable to determine type of boot loader. Defaulting to LILO.");
1325 res = run_lilo(offer_to_hack_scripts);
1326 }
1327#endif
1328 mr_free(device);
1329 mr_free(name);
1330
1331 retval += res;
1332 if (res) {
1333 log_to_screen("Your boot loader returned an error");
1334 } else {
1335 log_to_screen("Your boot loader ran OK");
1336 }
1337 return (retval);
1338}
1339
1340/**************************************************************************
1341 *END_ RUN_BOOT_LOADER *
1342 **************************************************************************/
1343
1344
1345
1346/**
1347 * Attempt to find the user's editor.
1348 * @return The editor found ("vi" if none could be found).
1349 * @note The returned string points to static storage that will be overwritten with each call.
1350 */
1351char *find_my_editor(void) {
1352
1353 char *tmp = NULL;
1354 static char output[MAX_STR_LEN];
1355
1356 tmp = find_home_of_exe("pico");
1357 if (tmp) {
1358 strcpy(output, "pico");
1359 } else {
1360 mr_free(tmp);
1361 tmp = find_home_of_exe("nano");
1362 if (tmp) {
1363 strcpy(output, "nano");
1364 } else {
1365 mr_free(tmp);
1366 tmp = find_home_of_exe("joe");
1367 if (tmp) {
1368 strcpy(output, "joe");
1369 } else {
1370 strcpy(output, "vi");
1371 }
1372 }
1373 }
1374 mr_free(tmp);
1375
1376 tmp = find_home_of_exe(output);
1377 if (!tmp) {
1378 log_msg(2, " (find_my_editor) --- warning - %s not found", output);
1379 }
1380 mr_free(tmp);
1381 return (output);
1382}
1383
1384
1385/**
1386 * Install GRUB on @p bd.
1387 * @param offer_to_run_stabgrub If TRUE, then offer to hack the user's fstab for them.
1388 * @param bd The boot device where GRUB is installed.
1389 * @return 0 for success, nonzero for failure.
1390 */
1391int run_grub(bool offer_to_run_stabgrub, char *bd)
1392{
1393 /** malloc **/
1394 char *command = NULL;
1395 char *boot_device = NULL;
1396 char *tmp = NULL;
1397 char *editor = NULL;
1398 char *p = NULL;
1399
1400 bool done;
1401 int res = 0; /* FALSE */
1402 bool mntlistchg = FALSE;
1403 FILE *fin = NULL;
1404
1405 assert_string_is_neither_NULL_nor_zerolength(bd);
1406 mr_asprintf(boot_device, "%s", bd);
1407
1408 if (offer_to_run_stabgrub
1409 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1410 /* interactive mode */
1411 mvaddstr_and_log_it(g_currentY,
1412 0,
1413 "Modifying fstab, mtab, device.map and menu.lst/grub.cfg, and running GRUB... ");
1414 /* Did we changed the mountlist ? If yes, then force editing conf files */
1415 if ((fin = fopen(MONDO_MNTLISTCHG, "r")) != NULL) {
1416 mntlistchg = TRUE;
1417 }
1418 for (done = FALSE; !done;) {
1419 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1420 if (p == NULL) {
1421 done = TRUE;
1422 mr_free(p);
1423 /* we want some warnings later on */
1424 res = 1;
1425 continue;
1426 }
1427 /* Only try to adapt grub here first if the mountlist wasn't changed before */
1428 if (! mntlistchg) {
1429 mr_asprintf(command, "stabgrub-me %s", p);
1430 mr_free(p);
1431
1432 res = run_program_and_log_output(command, 1);
1433 mr_free(command);
1434 }
1435
1436 if ((res) || (mntlistchg)) {
1437 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");
1438 } else {
1439 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");
1440 }
1441 if (!g_text_mode) {
1442 newtSuspend();
1443 }
1444 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1445 paranoid_system(tmp);
1446 mr_free(tmp);
1447
1448 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1449 paranoid_system(tmp);
1450 mr_free(tmp);
1451
1452 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1453 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1454 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1455 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1456 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/grub.cfg")) {
1457 mr_asprintf(tmp, "chroot %s %s /boot/grub2/grub.cfg", MNT_RESTORING, editor);
1458 }
1459 paranoid_system(tmp);
1460 mr_free(tmp);
1461
1462 if (does_file_exist(MNT_RESTORING"/boot/grub/device.map")) {
1463 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1464 } else if (does_file_exist(MNT_RESTORING"/boot/grub2/device.map")) {
1465 mr_asprintf(tmp, "chroot %s %s /boot/grub2/device.map", MNT_RESTORING, editor);
1466 }
1467 paranoid_system(tmp);
1468 mr_free(tmp);
1469
1470 if (!g_text_mode) {
1471 newtResume();
1472 }
1473 mr_asprintf(command, "stabgrub-me %s", boot_device);
1474 res = run_program_and_log_output(command, 1);
1475 mr_free(command);
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 mr_asprintf(editor, "%s", find_my_editor());
1491
1492 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1493 paranoid_system(tmp);
1494 mr_free(tmp);
1495
1496 mr_asprintf(tmp, "chroot %s %s /etc/mtab", MNT_RESTORING, editor);
1497 paranoid_system(tmp);
1498 mr_free(tmp);
1499
1500 if (does_file_exist(MNT_RESTORING"/boot/grub/menu.lst")) {
1501 mr_asprintf(tmp, "chroot %s %s /boot/grub/menu.lst", MNT_RESTORING, editor);
1502 } else if (does_file_exist(MNT_RESTORING"/boot/grub/grub.cfg")) {
1503 mr_asprintf(tmp, "chroot %s %s /boot/grub/grub.cfg", MNT_RESTORING, editor);
1504 }
1505 paranoid_system(tmp);
1506 mr_free(tmp);
1507
1508 mr_asprintf(tmp, "chroot %s %s /boot/grub/device.map", MNT_RESTORING, editor);
1509 paranoid_system(tmp);
1510 mr_free(tmp);
1511 mr_free(editor);
1512
1513 if (!g_text_mode) {
1514 newtResume();
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,
1528 0,
1529 "Running GRUB... ");
1530 log_it("%s",command);
1531 res = run_program_and_log_output(command, 1);
1532 mr_free(command);
1533
1534 if (res) {
1535 popup_and_OK
1536 ("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.");
1537 newtSuspend();
1538 paranoid_system("chroot " MNT_RESTORING);
1539 newtResume();
1540 popup_and_OK("Thank you.");
1541 }
1542 }
1543 mr_free(boot_device);
1544
1545 if (res) {
1546 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1547 log_to_screen
1548 ("GRUB ran w/error(s). See %s for more info.", MONDO_LOGFILE);
1549 log_msg(1, "Type:-");
1550 log_msg(1, " mount-me");
1551 log_msg(1, " chroot " MNT_RESTORING);
1552 log_msg(1, " mount /boot");
1553 log_msg(1, " grub-install '(hd0)'");
1554 log_msg(1, " exit");
1555 log_msg(1, " unmount-me");
1556 log_msg(1,
1557 "If you're really stuck, please e-mail the mailing list.");
1558 } else {
1559 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1560 }
1561
1562 return (res);
1563}
1564
1565/**************************************************************************
1566 *END_RUN_GRUB *
1567 **************************************************************************/
1568
1569
1570/**
1571 * Install ELILO on the user's boot drive (determined by elilo.conf).
1572 * @param offer_to_run_stabelilo If TRUE, then offer to hack the user's fstab for them.
1573 * @return 0 for success, nonzero for failure.
1574 */
1575int run_elilo(bool offer_to_run_stabelilo)
1576{
1577 /** malloc **/
1578 char *command = NULL;
1579 char *tmp = NULL;
1580 char *editor = NULL;
1581
1582 int res;
1583 int done;
1584
1585 if (offer_to_run_stabelilo
1586 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1587
1588 /* interactive mode */
1589 {
1590 mvaddstr_and_log_it(g_currentY,
1591 0,
1592 "Modifying fstab and elilo.conf... ");
1593 mr_asprintf(command, "stabelilo-me");
1594 res = run_program_and_log_output(command, 3);
1595 mr_free(command);
1596
1597 if (res) {
1598 popup_and_OK
1599 ("You will now edit fstab and elilo.conf, to make sure they match your new mountlist.");
1600 for (done = FALSE; !done;) {
1601 if (!g_text_mode) {
1602 newtSuspend();
1603 }
1604 mr_asprintf(editor, "%s", find_my_editor());
1605
1606 mr_asprintf(tmp, "chroot %s %s /etc/fstab", MNT_RESTORING, editor);
1607 paranoid_system(tmp);
1608 mr_free(tmp);
1609
1610 mr_asprintf(tmp, "chroot %s %s /etc/elilo.conf", MNT_RESTORING, editor);
1611 paranoid_system(tmp);
1612 mr_free(tmp);
1613
1614 mr_free(editor);
1615
1616 if (!g_text_mode) {
1617 newtResume();
1618 }
1619// newtCls();
1620 if (ask_me_yes_or_no("Edit them again?")) {
1621 continue;
1622 }
1623 done = TRUE;
1624 }
1625 } else {
1626 log_to_screen("elilo.conf and fstab were modified OK");
1627 }
1628 } else
1629 /* nuke mode */
1630 {
1631 res = TRUE;
1632 }
1633 return (res);
1634}
1635
1636/**************************************************************************
1637 *END_RUN_ELILO *
1638 **************************************************************************/
1639
1640
1641/**
1642 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
1643 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
1644 * @return 0 for success, nonzero for failure.
1645 */
1646int run_lilo(bool offer_to_run_stablilo)
1647{
1648 /** malloc **/
1649 char *command = NULL;
1650 char *tmp = NULL;
1651 char *editor = NULL;
1652
1653 int res;
1654 int done;
1655 bool run_lilo_M = FALSE;
1656
1657 if (!run_program_and_log_output
1658 ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
1659 run_lilo_M = TRUE;
1660 }
1661
1662 if (offer_to_run_stablilo
1663 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
1664
1665 /* interactive mode */
1666 {
1667 mvaddstr_and_log_it(g_currentY,
1668 0,
1669 "Modifying fstab and lilo.conf, and running LILO... ");
1670 mr_asprintf(command, "stablilo-me");
1671 res = run_program_and_log_output(command, 3);
1672 mr_free(command);
1673
1674 if (res) {
1675 popup_and_OK
1676 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
1677 for (done = FALSE; !done;) {
1678 if (!g_text_mode) {
1679 newtSuspend();
1680 }
1681 mr_asprintf(editor, "%s", find_my_editor());
1682
1683 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1684 paranoid_system(tmp);
1685 mr_free(tmp);
1686
1687 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
1688 paranoid_system(tmp);
1689 mr_free(tmp);
1690
1691 mr_free(editor);
1692
1693 if (!g_text_mode) {
1694 newtResume();
1695 }
1696// newtCls();
1697 if (ask_me_yes_or_no("Edit them again?")) {
1698 continue;
1699 }
1700 res =
1701 run_program_and_log_output("chroot " MNT_RESTORING
1702 " lilo -L", 3);
1703 if (res) {
1704 res =
1705 run_program_and_log_output("chroot " MNT_RESTORING
1706 " lilo", 3);
1707 }
1708 if (res) {
1709 done =
1710 ask_me_yes_or_no
1711 ("LILO failed. Re-edit system files?");
1712 } else {
1713 done = TRUE;
1714 }
1715 }
1716 } else {
1717 log_to_screen("lilo.conf and fstab were modified OK");
1718 }
1719 } else
1720 /* nuke mode */
1721 {
1722 mvaddstr_and_log_it(g_currentY,
1723 0,
1724 "Running LILO... ");
1725 res =
1726 run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
1727 3);
1728 if (res) {
1729 res =
1730 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
1731 3);
1732 }
1733 if (res) {
1734 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1735 log_to_screen
1736 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
1737 } else {
1738 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1739 }
1740 }
1741 if (run_lilo_M) {
1742 run_program_and_log_output("chroot " MNT_RESTORING
1743 " lilo -M /dev/hda", 3);
1744 run_program_and_log_output("chroot " MNT_RESTORING
1745 " lilo -M /dev/sda", 3);
1746 }
1747 return (res);
1748}
1749
1750/**************************************************************************
1751 *END_RUN_LILO *
1752 **************************************************************************/
1753
1754
1755/**
1756 * Install a raw MBR onto @p bd.
1757 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
1758 * @param bd The device to copy the stored MBR to.
1759 * @return 0 for success, nonzero for failure.
1760 */
1761int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
1762{
1763 /** malloc **/
1764 char *command = NULL;
1765 char *boot_device = NULL;
1766 char *tmp = NULL;
1767 char *editor;
1768 char *p = NULL;
1769 int res;
1770 int done;
1771
1772 assert_string_is_neither_NULL_nor_zerolength(bd);
1773
1774 mr_asprintf(boot_device, "%s", bd);
1775
1776 if (offer_to_hack_scripts
1777 && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
1778 /* interactive mode */
1779 mvaddstr_and_log_it(g_currentY, 0,
1780 "Modifying fstab and restoring MBR... ");
1781 for (done = FALSE; !done;) {
1782 if (!run_program_and_log_output("which vi", FALSE)) {
1783 popup_and_OK("You will now edit fstab");
1784 if (!g_text_mode) {
1785 newtSuspend();
1786 }
1787 mr_asprintf(editor, "%s", find_my_editor());
1788 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
1789 mr_free(editor);
1790
1791 paranoid_system(tmp);
1792 mr_free(tmp);
1793 if (!g_text_mode) {
1794 newtResume();
1795 }
1796 }
1797 p = popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device);
1798 if (p == NULL) {
1799 done = TRUE;
1800 mr_free(p);
1801 /* we want some warnings later on */
1802 res = 1;
1803 continue;
1804 }
1805 mr_asprintf(command, "stabraw-me %s", p);
1806 mr_free(p);
1807
1808 res = run_program_and_log_output(command, 3);
1809 mr_free(command);
1810
1811 if (res) {
1812 done = ask_me_yes_or_no("Modifications failed. Re-try?");
1813 } else {
1814 done = TRUE;
1815 }
1816 }
1817 } else {
1818 /* nuke mode */
1819 mr_asprintf(command, "raw-MR %s "MINDI_CACHE"/mountlist.txt", boot_device);
1820 log_msg(2, "run_raw_mbr() --- command='%s'", command);
1821
1822 mvaddstr_and_log_it(g_currentY, 0,
1823 "Restoring MBR... ");
1824 res = run_program_and_log_output(command, 3);
1825 mr_free(command);
1826 }
1827 mr_free(boot_device);
1828
1829 if (res) {
1830 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1831 log_to_screen
1832 ("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
1833 } else {
1834 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1835 }
1836 return (res);
1837}
1838
1839/**************************************************************************
1840 *END_RUN_RAW_MBR *
1841 **************************************************************************/
1842
1843
1844
1845/**
1846 * malloc() and set sensible defaults for the mondorestore filename variables.
1847 * @param bkpinfo The backup information structure. Fields used:
1848 * - @c bkpinfo->tmpdir
1849 * - @c bkpinfo->disaster_recovery
1850 */
1851void setup_MR_global_filenames()
1852{
1853 assert(bkpinfo != NULL);
1854
1855 malloc_string(g_filelist_imagedevs);
1856 malloc_string(g_imagedevs_restthese);
1857 malloc_string(g_mondo_home);
1858
1859 sprintf(g_filelist_imagedevs, "%s/tmp/filelist.imagedevs", bkpinfo->tmpdir);
1860 sprintf(g_imagedevs_restthese, "%s/tmp/imagedevs.restore-these", bkpinfo->tmpdir);
1861 if (! bkpinfo->disaster_recovery) {
1862 /* TODO: We need to get mondorestore.cfg and mountlist.txt from initrd.img */
1863 get_cfg_file_from_initrd();
1864 }
1865}
1866
1867/**************************************************************************
1868 *END_SET_GLOBAL_FILENAME *
1869 **************************************************************************/
1870
1871
1872/**
1873 * Copy @p input_file (containing the result of a compare) to @p output_file,
1874 * deleting spurious "changes" along the way.
1875 * @param output_file The output file to write with spurious changes removed.
1876 * @param input_file The input file, a list of changed files created by a compare.
1877 */
1878void streamline_changes_file(char *output_file, char *input_file)
1879{
1880 FILE *fin;
1881 FILE *fout;
1882 char *incoming = NULL;
1883
1884 assert_string_is_neither_NULL_nor_zerolength(output_file);
1885 assert_string_is_neither_NULL_nor_zerolength(input_file);
1886
1887 if (!(fin = fopen(input_file, "r"))) {
1888 log_OS_error(input_file);
1889 return;
1890 }
1891 if (!(fout = fopen(output_file, "w"))) {
1892 fatal_error("cannot open output_file");
1893 }
1894 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
1895 if (strncmp(incoming, "etc/adjtime", 11)
1896 && strncmp(incoming, "etc/mtab", 8)
1897 && strncmp(incoming, "tmp/", 4)
1898 && strncmp(incoming, "boot/map", 8)
1899 && !strstr(incoming, "incheckentry")
1900 && strncmp(incoming, "etc/mail/statistics", 19)
1901 && strncmp(incoming, "var/", 4))
1902 fprintf(fout, "%s", incoming); /* don't need \n here, for some reason.. */
1903 mr_free(incoming);
1904 }
1905 mr_free(incoming);
1906 paranoid_fclose(fout);
1907 paranoid_fclose(fin);
1908}
1909
1910/**************************************************************************
1911 *END_STREAMLINE_CHANGES_FILE *
1912 **************************************************************************/
1913
1914
1915/**
1916 * Give the user twenty seconds to press Ctrl-Alt-Del before we nuke their drives.
1917 */
1918void twenty_seconds_til_yikes()
1919{
1920 int i;
1921 /* MALLOC * */
1922 char *tmp = NULL;
1923
1924 if (does_file_exist("/tmp/NOPAUSE")) {
1925 return;
1926 }
1927 open_progress_form("CAUTION",
1928 "Be advised: I am about to ERASE your hard disk(s)!",
1929 "You may press Ctrl+Alt+Del to abort safely.",
1930 "", 20);
1931 for (i = 0; i < 20; i++) {
1932 g_current_progress = i;
1933 mr_asprintf(tmp, "You have %d seconds left to abort.", 20 - i);
1934 update_progress_form(tmp);
1935 mr_free(tmp);
1936 sleep(1);
1937 }
1938 close_progress_form();
1939}
1940
1941/**************************************************************************
1942 *END_TWENTY_SECONDS_TIL_YIKES *
1943 **************************************************************************/
1944
1945
1946/**
1947 * Unmount all devices in @p p_external_copy_of_mountlist.
1948 * @param p_external_copy_of_mountlist The mountlist to guide the devices to unmount.
1949 * @return 0 for success, nonzero for failure.
1950 */
1951int unmount_all_devices(struct mountlist_itself
1952 *p_external_copy_of_mountlist)
1953{
1954 struct mountlist_itself *mountlist;
1955 int retval = 0, lino, res = 0, i;
1956 char *command = NULL;
1957 char *tmp = NULL;
1958
1959 assert(p_external_copy_of_mountlist != NULL);
1960
1961 mountlist = malloc(sizeof(struct mountlist_itself));
1962 memcpy((void *) mountlist, (void *) p_external_copy_of_mountlist,
1963 sizeof(struct mountlist_itself));
1964 sort_mountlist_by_mountpoint(mountlist, 0);
1965
1966 run_program_and_log_output("df -m -P", 3);
1967 mvaddstr_and_log_it(g_currentY, 0, "Unmounting devices ");
1968 open_progress_form("Unmounting devices",
1969 "Unmounting all devices that were mounted,",
1970 "in preparation for the post-restoration reboot.",
1971 "", mountlist->entries);
1972 if (chdir("/")) {
1973 // FIXME
1974 }
1975 for (i = 0;
1976 i < 10
1977 &&
1978 run_program_and_log_output
1979 ("ps | grep buffer | grep -v \"grep buffer\"", TRUE) == 0;
1980 i++) {
1981 sleep(1);
1982 log_msg(2, "Waiting for buffer() to finish");
1983 }
1984
1985 sync();
1986
1987 mr_asprintf(tmp, "cp -f %s " MNT_RESTORING "/var/log", MONDO_LOGFILE);
1988 if (run_program_and_log_output(tmp, FALSE)) {
1989 log_msg(1,
1990 "Error. Failed to copy log to PC's /var/log dir. (Mounted read-only?)");
1991 }
1992 paranoid_free(tmp);
1993 if (does_file_exist("/tmp/DUMBASS-GENTOO")) {
1994 run_program_and_log_output("mkdir -p " MNT_RESTORING
1995 "/mnt/.boot.d", 5);
1996 }
1997
1998 /* Unmounting the local /proc and /sys first */
1999 run_program_and_log_output("umount -d " MNT_RESTORING "/proc",3);
2000 run_program_and_log_output("umount -d " MNT_RESTORING "/sys",3);
2001
2002 for (lino = mountlist->entries - 1; lino >= 0; lino--) {
2003 if (!strcmp(mountlist->el[lino].mountpoint, "lvm")) {
2004 continue;
2005 }
2006 mr_asprintf(tmp, "Unmounting device %s ", mountlist->el[lino].device);
2007 update_progress_form(tmp);
2008
2009 if (is_this_device_mounted(mountlist->el[lino].device)) {
2010 if (!strcmp(mountlist->el[lino].mountpoint, "swap")) {
2011 mr_asprintf(command, "swapoff %s", mountlist->el[lino].device);
2012 } else {
2013 if (!strcmp(mountlist->el[lino].mountpoint, "/1")) {
2014 mr_asprintf(command, "umount -d %s/", MNT_RESTORING);
2015 log_msg(3,
2016 "Well, I know a certain kitty-kitty who'll be sleeping with Mommy tonight...");
2017 } else {
2018 mr_asprintf(command, "umount -d " MNT_RESTORING "%s", mountlist->el[lino].mountpoint);
2019
2020 /* To support latest Ubuntu where /var is a separate FS
2021 * Cf: http://linux.derkeiler.com/Mailing-Lists/Ubuntu/2007-04/msg01319.html
2022 * we need to create some dirs under the real / before unmounting it */
2023 if (!strcmp(mountlist->el[lino].mountpoint, "/")) {
2024 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/lock", FALSE);
2025 run_program_and_log_output("mkdir -p " MNT_RESTORING "/var/run", FALSE);
2026 }
2027 }
2028 }
2029 log_msg(10, "The 'umount' command is '%s'", command);
2030 res = run_program_and_log_output(command, 3);
2031 mr_free(command);
2032 } else {
2033 mr_strcat(tmp, "...not mounted anyway :-) OK");
2034 res = 0;
2035 }
2036 g_current_progress++;
2037 if (res) {
2038 mr_strcat(tmp, "...Failed");
2039 retval++;
2040 log_to_screen(tmp);
2041 } else {
2042 log_msg(2, tmp);
2043 }
2044 paranoid_free(tmp);
2045 }
2046 close_progress_form();
2047 if (retval) {
2048 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
2049 } else {
2050 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
2051 }
2052 if (retval) {
2053 log_to_screen("Unable to unmount some of your partitions.");
2054 } else {
2055 log_to_screen("All partitions were unmounted OK.");
2056 }
2057 free(mountlist);
2058 return (retval);
2059}
2060
2061/**************************************************************************
2062 *END_UNMOUNT_ALL_DEVICES *
2063 **************************************************************************/
2064
2065/**************************************************************************
2066 *END_GET_CFG_FILE_FROM_ARCHIVE *
2067 **************************************************************************/
2068
2069/* @} - end restoreUtilityGroup */
2070
2071void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage)
2072{
2073 struct raidlist_itself *raidlist;
2074 int unfinished_mdstat_devices = 9999;
2075 int i = 0;
2076 char *screen_message = NULL;
2077
2078 raidlist = malloc(sizeof(struct raidlist_itself));
2079
2080 assert(wait_for_percentage <= 100);
2081 log_it("wait_until_software_raids_are_prepped");
2082 while (unfinished_mdstat_devices > 0) {
2083 // FIXME: Prefix '/dev/' should really be dynamic!
2084 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2085 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
2086 log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
2087 return;
2088 }
2089 for (unfinished_mdstat_devices = 0; i <= raidlist->entries; i++) {
2090 if (raidlist->el[i].progress < wait_for_percentage) {
2091 unfinished_mdstat_devices++;
2092 if (raidlist->el[i].progress == -1) // delayed while another partition inits
2093 {
2094 continue;
2095 }
2096 log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
2097 mr_asprintf(screen_message, "Sync'ing %s", raidlist->el[i].raid_device);
2098 open_evalcall_form(screen_message);
2099 mr_free(screen_message);
2100
2101 while (raidlist->el[i].progress < wait_for_percentage) {
2102 log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
2103 update_evalcall_form(raidlist->el[i].progress);
2104 sleep(2);
2105 // FIXME: Prefix '/dev/' should really be dynamic!
2106 if (parse_mdstat(MDSTAT_FILE, raidlist, "/dev/")) {
2107 break;
2108 }
2109 }
2110 close_evalcall_form();
2111 }
2112 }
2113 }
2114 paranoid_free(raidlist);
2115}
2116
2117
Note: See TracBrowser for help on using the repository browser.